What do you want to learn? Leverged jhuang@tampa.cgsinc.com Skip to main content Pluralsight uses cookies.Learn more about your privacy Organizing JavaScript Functionality by Kyle Simpson Before you use a framework, learn how to organize the different bits of JavaScript (modularizing, decoupling, etc.) with this intermediate JavaScript course. Start CourseBookmarkAdd to Channel Table of contents Description Transcript Exercise files Discussion Recommended Beyond the Basics Nested Scopes Basically we're going to kind of switch into chapter two mode, so if you're following along you can switch into chapter two, and I'm going to skip over some of the initial parts of chapter two. Basically the first half of chapter two is kind of layering on extra details that we glossed over in chapter one. So, for example, this comparing values and talking about coercion. I talk about it in more detail here than I do in chapter one. There's even much more detail than that in the books in the series, so these are just different layers, and so without getting too much into the weeds I'll just say that if you want to spend some time going through chapter two this'll definitely layer on more details for you about intricate nuances of the JavaScript language, but what we want to focus on is more towards the middle and second half of this chapter where it starts to push some of our understanding of these features a little bit further, so in particular, I'll call your attention to, for example, this example. Let me pull that out, copy it over to a code editor, and I'm going to zoom out just so we can see all of it. Okay, so here what you see is I've got an outer function called foo, but I also have an inner function called bar. That's a thing that we haven't seen yet, but it turns out that functions can be nested inside of other functions, and you can keep going as deep as you need to, and that may seem like, I'm not really sure why that would be useful. There's lots of different places in complex JavaScript applications where that sort of thing happens. So here though is this function baz is declared, and then I call baz here, but if I were to try to call baz down here on line 16 I wouldn't be able to because that identifier, baz, exists only inside of the scope of bar. Remember, we can't go down in scope, we can only go upward in scope. So here inside of the foo function I would not have access to the baz that only exists here in these lines, but the reverse I do have access. If I access the variable a, even though that's available two levels up, I'm still able to access it. So I can print 1 2 3 as I do here on line 10. So this idea of nested scopes is actually really, really important to how we structure sophisticated JavaScript programs. Particularly, not even the three levels deep, but particularly this where we have one function inside of another function. I kind of alluded earlier that that's kind of the gateway into this topic of closure. So another thing that we deal with in chapter two is talking --- motivating, what is this topic of closure and why is it useful? Now this may look a little bit complex. I'm not going to get into the details of how closure works. I'm just going to illustrate what closure does, so that you can observe it. So what we want to talk about with closure, and let me scroll down here to where closure is discussed. What we want to talk about with closure is this example that I'll use, and I will build this example up piece by piece for you. So I have a function here called makeAdder that takes a single parameter. Let me zoom in slightly. This is makeAdder, and it takes a single parameter, could be like a number that we pass in, and you'll notice that inside I declare another function called add, and inside of that I reference both the parameter, y, which of course I have access to the parameter, y, because it's a variable for me to use, but I also have access to x because of my scoping, because of my nested scoping. So I make reference to both of those variables in this add function, and then I do something rather peculiar, if you haven't seen this programming technique before, which is that when I return a value from this makeAdder I don't return a number, or a string, or a Boolean, I actually return the function itself. Remember, I said earlier that functions are values, and I showed very quickly that you could sort of pass a function in? Well, here I'm doing the reverse. I'm returning a function back out. Now that won't look like that makes much sense if this is your first time seeing it. Closure does take a while to get used to, but take my word for it, it's one of the most powerful programming techniques across any programming language, and it is intrinsically one of the most important things that you can learn about JavaScript specifically. So we'll just take for granted that when we call a makeAdder we're going to get a function back. Let's not worry too much about the implementation details. So if I said something like, makeAdder(5) the return value from that is a function, right? So if I assign that to a variable like, fn, what I've gotten back is a function, a function that I can later call, and you remember, let me switch back over here, you remember that makeAdder expects one parameter, and the function that it gives back expects another parameter, which we called y, so here I know that if I could pass something in, like for example, the value 10, what I know is going to happen under the scenes is that that 5 value that I initially passed in, plus the 10 value that I just passed in, both of those get added together, and that return result comes back. So if I say function 10, what am I expecting back? Fifteen. You see, I didn't have to pass in the five here because the function I got back already is set up to remember the five from the initial call. Now that mechanism looks a little weird and mind bending. It took me months of trying to wrap my head around it when I first learned it, so don't feel bad if that looks strange to you, but that is the essence of closure and people if you've ever heard that word before. If you've never heard the word before it probably just sounds like I'm talking nonsense, but there is this technique in programming called closure. What it refers to is the fact that this function as a value, we haven't even called it yet, as a value it is able to remember what was going on in the place where it was created. Remember, it was created right here, and the thing that it's able to remember is that specific x variable. So at the time we called it, we passed in a 5, and that function now, from here on out, no matter how many times we call it, if I say function 10, then I'll get 15 back. If I later called function 20, then I'd get what? (Student) Twenty five back. Twenty five. No matter how many times I call that function it's always going to remember that initial thing that I passed in at the time it was created, and that's what we mean by closure. So is there a question here? (Student) Yeah, it might have been a little bit further back there. Yeah, is 10 y? Yes. On this line 4 when I pass in 10 that's getting assigned to the y parameter. Modules Okay, so you may still be kind of like, oh that's crazy, that's mind bending, what kind of weirdness are you creating here? I do expound upon this more in the chapter, but let me show you one other way, and this is much more applicable to the coding that we're going to be doing for the rest of today. One other way that we can use that closure trick to our advantage, and it's called the module design. Module is perhaps the most important design pattern in all of JavaScript. It's certainly the most prolific design pattern. So again, remember the pattern that we want to look for is having an outer function and an inner function. Without fully understanding the mechanics of closure, if you just look for that pattern where function sits inside of another you'll know that's how closure ends up getting created, having one inside of the other. So if I wanted to be able to hide some details, I could have an outer function called Hello, and in here it could take a name as its initial parameter, and inside of here I could have a function called speak that uses that name variable. Does everybody see how that name variable is accessible to it? Because of the scoping thing, right? I can always walk up and find it in an upper level. So that function speak, if I return function speak this is exactly like we just saw with makeAdder. I'm returning a function back, and I know if I say fn = Hello("Kyle"), then now I have a function that every time I call it it's going to annoyingly say the name Kyle. Right? Super useful function. Maybe the most useful function I've ever taught you is a function that when you call it all it does is it prints my name. That'll probably be one of the cornerstone foundations of all of your JavaScript programming is that, okay? So for those of you online I'm joking, obviously. Okay, so if I return a function that's great, but what happens if I return something slightly more useful like an object? So we know we saw earlier that blocks, when we have a pair of curly braces that looks like a block, when a curly brace pair is used in the place where you would normally expect a value it's not a block, it's an object, and objects have properties and values on them, so let me just do a side note here. If I said something like, o equals a curly brace pair, and I put a property on it like super. Oh, let's not use super, let's use awesome as my property name, and the value is cool. So I have an object with one property on it, and that property has the value string, cool. That means later in my program I can say o.awesome and it will give me that value cool. So it's a way to put property values or function methods on an object, okay? Isn't there a way to call speak from outside the Hello function? So let's back up. If all I do is return speak here, the only way to call that is to call it with fn. If I tried to say, if I tried to say speak would that work or would that not work? (Student) It's out of scope. It's out of scope. Does everyone see that this name is only available inside? It's not available outside, by the same rules of scoping. We can go in one direction, we can go upward, but we can't go downward in the scope, okay? So I can't call speak here, but because I'm returning it, then I have access to be able to call it from the outside. So I can say, fn, and that's what lets me annoyingly print out Kyle. But now, if we consider instead of just passing back a single function, if we pass back an object, like this, and on that object I have a property name called speak, as we see here, that is referencing this internal one. These names do not have to match, but let's just make them match for now. If this is what I return from my function, instead of getting this as a function this is an object now. Does everybody see that? What I'm getting back is an object, not a function, and now what I can say, instead of saying o, open close parenthesis, because it's not a function, what I say is o., the property name, speak, and to hammer that point home, if I gave it an entirely different name, like say, then that's the name I could use on the outside. In other words, I have this internal function, which is only accessible inside of the hello function, and I have something on the outside that is accessible only as that external name, whatever I end up calling it. Is everybody following that or am I losing people? What if you passed in an argument to say? We could definitely set this up to accept an argument and then use it, I'm just keeping the example simple, but we could definitely set it up that I could pass in something like if I called this lastName we could definitely use that, and that would print it out. So see how that's exactly like the makeAdder that I was showing before? It remembers one variable from its closure, and it gets another one passed in. Same thing as what makeAdder was doing. So what we're seeing here is that returning this object from a function call is essentially creating what we, in programming terms, call a public API. The stuff that's on the inside, like this function, any variables that I might declare inside of there, all that stuff is completely private. We can't get at it from the outside world, but the stuff that we put in this object and return it back, that is accessible to the outside world, which is like a public API to access the internal module. (Student) Just some questions on what's better and why? Why would I return an object? An object will let me have multiple methods on my API, so if I had 15 inner functions, and I wanted to expose 5 of them, I could list all 5 of them here, and I'd have an API that had multiple public endpoints. So returning an object lets me put multiple things here. If the speak was the only function that was necessary to expose you could, of course, just return only the function. (Student) So, in other words, you could have the lastName as one of properties. You could have lastName and you could return lastName or firstName or whatever you find. If I said lastName here what value would I assign to it? (Student) Probably a lastName was passed in? You could conceivably want to assign off that lastName somewhere, but there's no way to access this object the way it's currently written to be able to do that, so a more realistic scenario is to suggest that we might have a method called firstName, which does nothing, it doesn't take anything, except it returns back the name that we initially passed in. So now I have two different methods, as we say, on my public API. One of them is say, which prints things out. The other one is firstName, which doesn't print anything out, but it returns back that initial value that I passed in, the value Kyle. So that's two different ways of defining these methods on my public API. Closure Q&A There's no question that the first time somebody shows you closure it bends your brain. The 10th time somebody shows you closure it's still bending your brain, so there should be no expectation, if this is your first time to see it, no expectation that it immediately just clicks. It takes a while, but what I would say is this probably comprises better than 95% of all code that I write is in some way, shape, or form relying upon an understanding of closure. So if you're looking for the next place to go once you feel like you have kind of a grasp on the mechanics of for loops and variables or whatever, the biggest conceptual thing that you could spend time trying to understand is closure. It's the most important. That's why it was the first book that I wrote in the series, because I wanted everybody to know, if you're looking for the first thing that you should spend some time making sure you get its closure. Modules are how I design most of my software. A lot of people are like that. They design software using this. This is what we call kind of the module pattern, and I don't have to think about how it works anymore because closure is natural to me now that I've been doing it for years. The first time you're doing it for years. The first time you're doing it you're having to remember, like hey, how is it able to access that name? Oh, it's because it's like inside and it still has access, okay, and you progressively get more and more of your head around that. At some point, it will be appropriate for each one of you to go read that scope and closures book, and I cover it in extreme detail exactly how it works. (Student) Is the reason you call it closures is because that stuff's closed to the outside world? Is that why you call it that? It's not a name that I invented. It's a term that was invented long before I was born. The etymology of that word as applied to this concept is that what it has said, this is just an academic side note, what it has said is this function speak, because it accesses the variable name outside of itself, it is said that speak closes over that variable, and that terminology actually comes from a branch of mathematics called lambda calculus, which I've never taken, and I don't even understand, so I'm not going to teach you lambda calculus, but that's the etymology actually goes all the way back to the concept of lambda calculus. As applied to programming, it's a super, super powerful mechanism, maybe the most important thing that ever happened to programming. I know that sounds like a radical statement to be making, but it's really, really important. It just takes some effort. It's not like a for loop where I can just show you a for loop and you get it, you've got to wrap your brain around it, you've got to try it a few times. (Student) Are we doing this because, like in other languages, you can specify things as private, and here you can't because you can kind of move stuff in and out, but this technique keeps you from doing that? It is true that JavaScript does not have a notion of private, other than using this idea of burying stuff inside of the scope, so putting some stuff inside of a function keeps it private, and there's a design principle in software engineering called the principle of least privilege or the principle of least exposure, and that design principle says, keep everything private by default, and expose only the minimal necessary to get the job done, rather than making everything always available. So here what we're saying is there would be definitely chances for me to have --- to expose both of these, but I could have a dozen other inner functions that I don't want you to have access to. They're implementation details, they're private things. If I don't expose it on the public API it's not available. So it does give us the mechanics of private scoping. (Student) Rather than creating the function, firstName, you could just return name, right? So the problem is this. If I, instead of having a function name here, if I just said name: name, because this name is a primitive value, it's just a string, if anything was allowed to change that later on, like if I had another thing like changeName, and that did this, and that changeName was a method that somebody could call outside. (Student) But are we doing something different? If I said, o.changeName("Marc"), and then I asked what is in o.name you would think that it would be Marc, but there's no such thing as pointers here, so when we made this it got sort of a copy of what it was at the time, so this would still print out Kyle. So that's the reason why you would want to use what, in programming terms, is called an accessor method. It's a function that I call to get some value out rather than the value itself. Kind of a getting into the weeds sort of a detail, but that's the main reason why I would have something called a firstName accessor method rather than the property itself. If it was never going to change, then there's no reason why you wouldn't just show it, so it would be okay here if we were never going to let you change it. Yeah? (Student) So I think we have a feud going back here starting at the if using closure does make it harder to test your functions, as you can't access them? That's a good question, and there's a really long and complicated way for me to answer that question, but I don't want us to get too far off track, so I will suggest, first of all, I've addressed that in the books, and the other teachings, but let me just give you a quick glance at that topic. It is true that if you hide something inside of this function, if I had 10 other functions here that were not exposed to the outside world, they're not exposed, and therefore, they're not testable. Some people think that the term unit testing, that's the most common term for how people test stuff, some people think that unit testing means everything has to be tested, and for them module design is kind of a negative because it looks like there's a bunch of stuff that I can't test, and there have been new patterns and techniques that have been invented to try to deal with that problem, the most notable of which is called dependency injection, where I can do this sort of weird like pass some stuff in and have it sort of magically access stuff or whatever. It's like trying to do contortions while playing the game, Twister. Like they want to have access to it, and they don't, so they make this back door that they get access to it or whatever. I think that's, my personal opinion, all that stuff is nonsense. There is absolutely no point to any of those contortions because I define unit testing in a much more reasonable fashion, in my opinion, which is that a unit is not just any function that I want to test. A unit is the smallest, indivisible piece of code that is used the way I'm going to use it in my real application. So let's imagine a module that has 100 inner functions, and just one public API method. In my definition the unit test only tests the one public API, and all the internal stuff is intentionally untested implementation detail. You're not supposed to test implementation detail. That's supposed to let you abstract the implementation details, and refactor, and not have it break all your tests. So my definition comes from the outside rather than from the inside, and there's a term for that, by the way. The term is whether you prefer what's called black box testing, which is I test from the outside having no knowledge of the inside, versus white box testing, which is I test having full knowledge of the inside. So my preference, when I do unit tests, is to test with a black box methodology. Test from the outside in, rather than the inside out. That's a 50,000 foot view of a really, really long, complex conversation, but hopefully it at least gets a couple of answers to that question. Let's scroll back up and see if I missed other questions. (Student) I think a lot of people are asking for a real world example of using this stuff. So modules are the answer to that question. Everything that we design is a module. Let's imagine you are designing a login page for your application, and there's an object that references the user, and it has internal properties, like their username, and their password, and their user id and stuff, and then on the outside you have a public API, like, is user logged in? And it just tells you true or false if they're logged in or not. That's a module. We've got some private stuff, we've got some public stuff. We've got methods that we can call. We've got inner data. That's a module. So basically anywhere that you would create anything even remotely conceptual like that, the most natural way to do that in JavaScript is with a module. (Student) So can you relate it to something like a class, in the case of an object oriented world? I taught an entire class on the topic of why classes in JavaScript are not correct, so I can't possibly answer that question to its fullness either. I hate to keep saying this, but I've got a whole book on it, so I would recommend reading the This and Object Prototypes book to get a fuller answer to that question, but when you define classes in a language like JavaScript you don't have any notion of encapsulation or privacy. The way classes are done in JavaScript, everything's public, everything's accessible, and modules have true encapsulation with true privacy, so if privacy matters the module is the much more natural design. (Student) I just want to point, he already mentioned his book, the Eloquent JavaScript book talks about this in such beautiful language. It does. It's absolutely true. I would definitely, again, I recommended it earlier, I would repeat that. Eloquent JavaScript's a great book to read as a companion to the stuff we're talking about. Okay, let's go back here. What kind of applications do they have? I hope I've answered that now. Basically everything. You have some questions about, does this come from Lisp? Yes, closure is a topic in lambda calculus that it first showed up in computer programming in the Lisp programming family. So to clarify return of the object. Yes, this object right here that I'm returning from lines 7 through 10, that object itself represents the public API of which there are two properties. One of them is a method, and one of them here is just a string value property, but that is the public API for our module. When you say private you just mean not accessible right, or do you mean not visible? Ah, great question. Not a dumb question at all. Private means accessible while running the program. It does not mean invisible to prying eyes when they do a view source. There is no such thing as that in JavaScript. All code that runs in a browser can be seen by a user, but what we mean by private versus public is what's accessible from any given location in your program can I access stuff. Okay, now I know, especially given some of the questions, I know that modules are already starting to push the envelope for some of you, and that's totally okay. The rest of what we're going to talk about today, this was the main thing I wanted to kind of go on, so we're going to take about a 10 minute break now to let some of that seep in, I'll answer if there are any more questions, but the whole rest of our course is no lecture from me, it's a full exercise with lots of different tasks and subtasks in it, and you're going to go little, by little, by little building yourself up, and along the way you're going to get some practice with this concept of how to do something with a module, and I will hold your hand through it, but we're going to apply all of this theory. So we've got the theory out of the way, hopefully, and now we're going to do the rest of the training, we're going to spend kind of applying that to an exercise, so if you're already feeling a little bit like, I don't know what's going on, it's okay. We'll go through it together, we'll talk through everything, but I do encourage you, especially if you've already got some experience with this, try your hand at the exercises. Even if it's confusing, there's value in the confusion. I know that's an unusual statement for a teacher to make, but there's actually value in the confusion. There's value in trying something without fully understanding it, and then layering on your understanding instead of never trying it because you don't fully understand it yet. Public vs. Private It was asked, what's the difference between something that's public and private, so I rearranged this slightly to show I now have an inner function here, which I call upper, and it does the task of taking some variable and uppercasing it, and then I have this function here, and I'm using that inner function, but you'll notice that I'm not exposing that upper to the outside world. That is an internal implementation detail that from the outside world you have no access to, but I'm still able to use it. So this is what we mean. This function that's declared on line three is an inner function, it's a private function. It's not accessible to the outside world, and we are likely going to make modules that have lots and lots of those, and lots and lots of private variables. Like, for example, the name variable that we see from line one, that's a private variable, but we can make other name variables. Like we could do id, and we could assign it a random number as that person's id, right? So now I have a user id that is only accessible on the inside, and the only way somebody can ever see that value is if I choose to make a method that exposes that in some way, otherwise, it stays private. So id now, and upper, and name those are all private things. The only thing that's public is I make a reference to that function on this object that I return back, that object being a public API. There's a slight variation of lines 13 through 15 that I personally do in my own code to make it slightly more clear what's happening, and it's this. Instead of returning that object I call it public_api, and then I return public_api. Now functionally, that's exactly the same as the previous, but this is slightly more obvious now what this object is. It's a public API. So if I'm looking through hundreds of lines of code, and I see a thing declared called public_api it kind of jumps out at me as like, hey, hey, there's a public API here, okay? It's just a stylistic choice that I prefer. Just to hammer home this point of the fact that this inner function still has access to stuff, I don't even have to use it in such a way where I'm passing something to it. Upper could be called upperFirstName, and it could be set to automatically use name, and so here I don't call upper and pass in name, I just call upperFirstName without needing to pass anything into it. It's still going to work exactly the same way. It's going to call this private inner function. That thing is going to have access to this variable through the closure, and it'll be able to receive that value and do something with it or use that value to do something. So that's why we end up printing KYLE in capital letters. Okay, let's ---. Now hopefully most people have, oh. Somebody's asking about my variable name text formatting. Yeah, it's kind of, I have my own sort of weird style that actually comes from programming prior to moving to JavaScript, so essentially, I CamelCase anything that is a function, and I use whatever this style's called, I never even remember what they call that, but --- (Student) Snake case. Snake case. There you go. I never remember. I use snake case for variables, and I use CamelCase for functions, and that's just so I remember, in my own code, is this something I can call or not? That's not a terribly common style that people use, but that's my own weird style. (Student) It's smart though, like it seems like a good style. I got that from way, way back, like C programming I did that, and it's just a habit that stuck with me, it's not a particularly idiomatic thing in JavaScript that a lot of people do, but that's how I came across it. (Student) Is JavaScript, no it probably isn't case sensitive where if you have like up there the Hello is in capitals. If you use hello with a small letter it's okay, right? It is not. JavaScript is completely case sensitive. (Student) It is case sensitive. Okay. All identifiers are case sensitive. (Student) Okay, good to know. Yeah, even in this own piece of code I was a little inconsistent because this lastName probably to keep consistent I probably should have called it last_name. Callbacks Let's imagine that I have some utility called foo, and I'm not even going to tell you what foo does, but foo does some work, and it doesn't finish right away. For example, there's a utility built in to JavaScript called setTimeout, and we can pass something to setTimeout, which is a function, and then we tell it how long we want it to wait before it runs that function. So if I had declared a function called bar that prints out Hello World, if I pass bar by name, notice no parentheses there, if I pass bar by name this utility, at some point later in the future, about 1000 milliseconds from now, it's going to call that function and print this out. So everybody try this. Try typing that code into your console, and copy it over and show you. So try typing that code into your console and running it, and what you'll see is that it waits for a second, and then it prints out Hello World. (Typing) So, essentially what I am doing is I am passing a function by its value. I'm not calling the function, I'm passing the function value. Similar to how we returned a function earlier, this is one where we're passing it in. Now this usage, passing a function as a value, is often called callbacks because I'm passing a function in that, at some point later in the future, and I don't care when, you're going to call back to my function. Sometimes you're just going to execute it like we're seeing here. Sometimes you're going to call back and you're going to pass me something. So an example of that is let's imagine back here that I have some utility defined by a library called ajax, and what ajax takes is two parameters. So when I call it I call ajax, and the first thing it expects is a URL, but the second parameter that it expects is a function. Okay? Now I'm going to name mine resp, so if I declare what that function looks like, function resp is expecting some content back from the ajax request, and I'm going to print it. So what's happening is I'm not calling rest, there's no parentheses here, I'm passing resp in by reference, by name, and at some later point after the ajax request finishes and it's got some content back, it's going to call my function, and pass that content in, so that I'm going to be able to print it. This isn't directly related to closure, but it's actually related to one of the base principles of closure, which is functions as first class values. That is, functions are a value just like the number 42 is a value, and the string, Hello World, is a value. They're all just values, and we can pass values all around wherever we want to, and we can return values wherever we want to. There's nothing special about a function that makes it more or less capable as a value than the number 42. Does that make sense? It's just a value that we can pass around. So, in this case, what we're saying is, I don't have the response from that ajax request yet. If I did have the response, if it was an immediate thing, like if it could happen right away, then I could just say var resp = ajax. I could just get it, but because ajax is not a blocking network request, it doesn't have the answer right away, and the way we then wait for that answer is to pass in a callback, and that callback will get called back at some later time with the answer that we were looking for. Asynchronous programming, which is essentially this is us dipping our toe into that pool, asynchronous programming is a fantastically complex branch of JavaScript programming, and there's tons and tons of stuff out there about it, books that I've written and many others have written, so we're not going to go any further than just understanding this concept that if I pass a function in somebody can call it at a later time. Organizing Code Exercises Overview So the folder is called jsorg, and let's start by opening up the README, just to orient ourselves. In this exercise you're going to modify an existing code to wire up basic interactivity for a simple site. The objective of this challenge is to exercise your skills with basic JavaScript, including events and DOM interactions, as well as some best practices for organizing code. In fact, it's that latter one that we more care about. We more care about seeing in practice how we organize JavaScript code than necessarily exactly how we deal with events and interactions, although there will be some practice with that. So we're going to use jQuery as our little library that helps us do events and interactions more easily. If you don't have any experience with jQuery at all that's totally cool because I'm going to show you the little bits and pieces that you need to know about it, but this is not a course on jQuery, so I'm not going to get much into the details of it, I'll just show you what to do, but there's one thing here, this note that I want to point out to you, and I wish there was a way for me to make this detail not something that you have to worry about. If there was any way I, as a teacher, could just make this detail go away I would. Unfortunately, we have a complicating detail here for you to run this exercise. Because we're going to be doing ajax requests inside of the exercise, if you're using Chrome or IE you're going to need something more than just running with these files themselves. If you choose Firefox, Firefox, at the moment, doesn't have a security restriction on it, and we're able to do ajax just from one file to another. So it's an easier story if you're using Firefox. If you're using something like Chrome or like IE like I am you're going to actually need to run a little local web server instance in the folder, so that you can load it up through local host in your browser rather than through the file system. So, if you're on a Mac this is actually really easy. If you're in the directory, as I am here, all you need to do, if you're on a recent Mac, is type in python -m, and then SimpleHTTPServer, and then the last parameter is a port number, which I always like 8005 for whatever reason. What this is going to do is spin up a simple static file server in that directory, so that we can access this, the contents of the directory, as if it was coming from a web server. If you're not running on a Mac, you can still get Python for free. You can download from python.org a Python interpreter, and it'll run very similar to this. It's a slightly different syntax, but it runs very similar to that, and you can do the same thing. Or you could use Apache or IIS or any of about a dozen other local web servers to run it. The easiest is if you're on a Mac and it's just built-in or if you want to go get Python from python.org and download it because it's just this simple one liner, but there are other options if you decide you want to go that route. Task 1 - Introduction Let's look at our app in page. I've implied a couple of things by this silly little design. One is that we've got a little carousel here that I should be able to go left and right in my carousel. You'll notice that it's not functional. We're going to let you wire up the events to make that functional, and then you'll notice this big, blue area over here on the right, what does that thing signify? Well, essentially that signifies a details pane that if I were to click one of these items in my carousel list it would show up a set of details about that person. So my stupid little example here is this is like a page for a company that provides tech support, and you're trying to schedule one of these individuals to come out to your office and help you with your computer, so you've got a list of the available tech support technicians that you can click on, and see their details, and figure out who you want to schedule, okay? So that's just my basic little metaphor for what this app is supposed to be. So we're going to wire up these events and these functionalities first, just getting our feet wet with using jQuery to do a couple of basic tasks, but our much more important focus here is on how the code that I've already written, how can we improve it to organize it better, and that's really where we're going to solidify a lot of the discussions that we were just having about what's the purpose of a module and a closure, whatever. We're going to see why that's such a useful tool for code organization, okay? So starting with the first task, it says, open up header.js, so let's do that. In your directory you're going to have a header.js file, js, header.js. Ah, it's empty. That's super not helpful, right? This is where you get to write some code, right? Now what's the purpose? What are we trying to have it do? It says to open up the file. Let's go back to the README. What's the purpose? In this file you're going to attach event handlers for the header links, and you want to use jQuery document-ready event handler to make sure that your code doesn't run too early, so first step, if you haven't had much experience with jQuery, is you're going to want, we can take out that comment, you're going to want to say, document.ready, and all the code that we're going to write right now we're going to put inside of that ready function. What document-ready does is there's a special event that your browser fires that lets you know that it is --- that the DOM has been parsed, and it's ready to go. So if we're going to do anything with the DOM, like we are here, we want to make sure that we're in a ready state. Now let's go back to the design, and if we look at the design here you'll notice that I've got a couple of links up here that imply or they link to pages, like one is for registering and one is for login. If I click them right now you'll notice I do a full page refresh, full page load, to one of those other files, which is not at all what I want. What I want, user experience wise, is that clicking on one of those links pops up that page in a modal, okay? Now the modal already exists. You don't have to define the modal or it's CSS or anything, but we need to actually invoke that modal and have it load the code, you know, load the URL from one of these links that's clicked on, okay? So our first step is to set up a click handler, and we want to figure out on what do I want to attach my click handler to? Well, there's some links there that we want to attach to, so you should probably open up the index.html and get a little bit familiar with the markup that I've provided. Specifically, I'll call your attention to these links right here, which are, in fact, the register and login links. So what we want to do is get those links and attach event handlers to them, so that when they are clicked they fire our event handlers rather than just doing a navigate. Now I've provided these rel attributes on all of these different elements that you need to interact with. You'll notice I'm saying the rel=, and then I have a value in there like js-register. There's lots of different schools of thought. We're on task one. It's being asked in the chat room what task. We're on task one, and we're on the first step of task one. There's lots of different schools of thought of how from your JavaScript code should you figure out what element in the DOM you want to interact with. A lot of people like to put an id on their element, and then look up the element by its id. It's a very common and very powerful, you know, practice or pattern. I'm not a big fan of that approach, and the reason is that id's are usually more used in your CSS. If I open up the CSS file that's provided with the site, probably the part that I'm least proud of because I'm not really a CSS person at all, but you'll notice in my CSS I have several places where I'm referencing elements by their id, like #page, I've got a few down here like #carousel. Ids are much more commonly associated with attaching styles to a specific element in your page, and the problem is, not on small projects, but on big projects what you'll very quickly learn in your JavaScript career is that it's very common for somebody to come through and refactor the markup of your page and change out the ids or to change the way the CSS works, and to pick different id values, and if your JavaScript is also relying on that information, then your JavaScript breaks. So it's just one more piece that you have to maintain. If you change an id, and it's used for CSS, and you change an id, and it's also used for JavaScript, now you've got to fix it in both places. So I prefer, I don't care what happens to the CSS folks. I'm not a CSS person, so they can do whatever they want, but in the JavaScript world I don't like to use ids because I don't like to have to worry that somebody's going to come back and make me have to change a bunch of my code. (Student) Just a quick aside, the SMACSS guy has the same thing to say about ids in relationship to CSS. Good. He's a smart dude, so that probably means that I'm --- (Student) Id's are out. --- I'm just cribbing off of some other smart person. So I don't like to use ids in my JavaScript. A lot of people use id's in JavaScript and class names only for CSS. Still, it's not my particular brand. So another thing that people will do is they will attach a data attribute. Now that's a new HTML5 thing. They'll attach a data attribute for looking at elements. My preferred approach, this is all just a preamble to say, my preferred approach is to use the rel attribute. The reason I like this attribute is that it is valid on nearly every single element in your page, but almost all elements it doesn't mean anything on them, so it's just sitting there valid, but it has no meaning, which means it's a nice little like hook for us to use. (Student) What was its purpose originally? So what rel means is relationship, okay? Now look at, for example, rel nofollow on an a tag. That's actually a real thing. That's not something I've made up. Rel no follow on a tags, what that tells the search engine is the relationship between the page that I'm linking to and my page is no relationship at all. Don't follow it. Don't give it any search engine juice, and that's a very common thing in the SEO world is to put nofollow relationships on your links; for pages that you're linking to for information, but you're not endorsing them in any way, okay? So here rel means the relationship between my page and some other page. Another place that rel is used that you'll very commonly see is on the link tag, and here the relationship is pointing at another file, not a URL, but another file, and it's saying the relationship between that file and my file is that I want to use him as a stylesheet, but in both of those places relationship means relationship between myself and some other entity. So I, Kyle, took that and extended it slightly, I pushed the envelope a little bit further, and I said, if I wanted to define a relationship between a DOM element and my JavaScript code, then I can use the rel attribute to give it some identifier for the relationship between element and JavaScript code. So that's why I like rel is that it defines a relationship here. In this case, it gives an identifier that I can hook to, and the relationship is telling me that's something I'm only going to use for JavaScript purposes. I'm not going to use it for any other purpose other than JavaScript. Lots of different schools of thought on it. You don't have to get too wrapped up. If you totally disagree with me, and you like to use ids or that's the way you end up, you know, if the company does that where you work that's totally fine too, but I like to use rel attributes. So the code that we're working with will already, that'll be kind of already going with the flow. Task 1 - Events All that was a long preamble to say, we want to attach click handlers to these two links, and there's a couple of different ways that we can do that, but the easiest is for me to say, you'll notice that there is a control, a js-controls wrapper div around the two header links. So if I were to find an element by attribute, and this is the syntax you use for finding things by attribute, we put brackets in, rel='js-controls'. What that means is go find any element in the page that has a rel attribute whose value is js-controls. So I'm saying here, go find one of those, and get me the child element, js-register. Ah, so a question about rels having more than one element. Yeah, as you'll notice here in my HTML, I've got multiple rel attributes here, and I only care about one of them. It's the js-register. Alright, so now I want to say a child element where the rel attribute has js-register somewhere in it, so that is almost the same, except we use *=js-register. That's one way of me getting it that link. You also might note that if I make js-register totally unique, then I don't even really need this part, and if I want both of these links to be attached with the same handler, which I do, I can use the compound syntax, I can do a comma here, and say rel*=js-login. So here I'm saying, go get me an element that has js-register as it's rel attribute, and another one that has js-login in its rel attribute. I know in my page there's only going to be one of each of those, so I know I now have a collection of only those two elements. There's literally a half dozen other ways that I can write that same line of code. You also should have been provided, in addition to the jsorg you would have gotten the jsorg-solutions folder, and you'll notice in that jsorg-solutions folder I have broken down task1, 2, 3, and 4. Those map to the tasks, the high level tasks that we're doing in our README. So task1 is the completed form of this task. Task2 is the completed form of task2 and so forth. So, if I took a quick little cheat peek at the solution file for header.js this is another way of doing it, which is I'm going to attach, not even to the controls, but to the header element itself, you'll notice in my index.html I also have an element here called js-header, and there's a thing called event bubbling, which means if I click on something and I don't have a handler on that the bubble will make that event fire on any of its parent elements too, so I could take advantage of attaching a click handler to the header element, and these link clicks will just bubble up for me, which is nice and convenient. So that's actually the way I'm going to prefer to do this, but like I said, there's like a dozen other ways that you could do it. (Student) Did you cover that --- what does that star mean? Star means find it anywhere in the value if you're going to have multiple values. So I'm instead going to attach to the header element. I'm going to attach a click handler, on("click"), and I want to limit my clicks to only ones that were on those js elements. So if we come back to our indx.html I want to limit it to js-register or js-login. There's a couple of different ways of going about that, but the easiest way to go about that is to give it a string that says, so it just needs to be one of the things that has a js- in it, and actually, I'm going to slightly switch from my solution file. We're going to use, or I'm going to go back to using controls rather than header here. Finally, we give it a click handler. So what we know inside of this function is that if we get this function called we know that one of our two links was clicked, which is what we wanted. We want to make sure that one of our two things was clicked. Now, in terms of event management with jQuery, you've probably, if you've had any experience with jQuery before or you've read stack overflow posts, you've probably seen people do things like return false, which we don't want to do here. So there's another way of managing this event, so that we handle it, and it doesn't bubble anywhere or do anything else, and that's to call evt.preventDefault, evt.stopPropagation, and evt.stopImmediatePropagation. So that just simply means that we're handling the event, we don't want it to bubble anywhere else, we're going to take care of it. Task 1 - AJAX The element that was clicked on is an a tag, right, which has an href in it, and that href is the URL that we want to load. We want to load that file up. We essentially want to make an ajax request for that file, get its contents, and stuff it into a modal. So I can get the URL by looking at the element that was clicked on, which is going to be evt.target, that's the link that we clicked on, and I want to jQueryify that element because I want helpers for it, so I'm just going to wrap dollar sign parentheses around that element, and I want to get its href attribute, and the way we do that in JavaScript is .attr("href"). Just double-check myself against the solution file here. Okay, so now I have the URL, jQuery has a nice simple syntax for doing ajax. If you don't want to type this part you're free to kind of just copy and paste it, which is what I'm going to do because I don't want to type it. So you can copy and paste from the solutions file if you'd like, but this is how we do an ajax call. I'm giving it the URL, and I'm telling it that I'm expecting to get back text, so that it doesn't do any parsing, and this .then is basically how I specify my callback. (Student) They're just wondering why you didn't use preventDefault. We did use preventDefault, but the question is why did I do the other two? We don't have to do the other two in this example, I just did it because there's a habit that I do. I call all three of those usually, just by habit, but in our particular situation we actually don't care about the propagation, we only care about stopping the default behavior, so it would be acceptable if you didn't put them in. So once I've loaded the contents up as an ajax request, remember, that looks exactly like we did before. There's an ajax call and I get a callback that I get some contents back. Now I need to add that to my modal. So we don't have this variable yet, but we can declare this variable, and have that variable point at the modal. So that's going to be our last step. We want to declare a variable called modal, and we want to get at it the same way we get at any other variable. Didn't understand the URL line, okay? The first thing is to get the element that was clicked on. That's what event.target is, and then the link, the a tag that we clicked on we want to get its href attribute. Want to get the value of the href attribute. So, in our index it would be getting this register.html or the login.html. That's the value we want to get. Okay, so how are we going to get a reference to the modal that we want to click on, or I mean that we want to add content to? Well, the way we get referenced to that, we come to our markup, and we find that there's a modal there with rel js-modal, so we get it exactly the same way we were getting the other ones, which is to say rel='js-modal'. I have a stylistic convention that you see on line three, which is that any variable that I declare in my code, which points at a jQuery object I always prefix my variable names with dollar signs, just to make it clearer that I'm dealing with a jQuery. (Student) There's nothing actually special about the dollar sign is there? Not in variable names there's not. (Student) There were just a few questions there. Could we have used $this? Did you cover that question? I didn't cover that question. The question is basically, do I need to do event.target or could I have used this? You do not want to use $this. I know that many people are familiar with and have seen that in a lot of places. It is not as reliable as you would expect. In our particular case it would have worked, but there are lots of other cases with event propagation, that is the bubbling stuff, where it doesn't point at what you want. JQuery makes sure that event.target always points at the thing that got clicked on, so it's a reliable parameter, and that's why I always use it out of that habit. (Student) The other question was, is .then native to JS? --- This is part of the jQuery API. This .then that's happening here, that's part of jQuery's API. (Student) So they're saying that that's not a promise. JQuery is not using real promises. JQuery is doing their own version of stuff that looks a little bit like a promise, but isn't. The other question is, are native promises coming to JavaScript? Yes, they are coming to ES6, it's just that these are not native promises, so the .then that you see there looks like it's a native promise, but it's actually just a jQuery API. I might have lost some of you already, even though I walked you through it, and that's totally okay. Don't feel frustrated and walk away, you know, walk out on me. The point that I'm making here is that we're already using some of the concepts that we talked about earlier in our course. For example, we're passing in a callback function, right? So if I just hid all of the contents, which I'm going to use a little trick in sublime that does code folding. Okay, so I just hid it temporarily, I'll bring it back in a minute, but if you look at this function, I mean if you look at this dollar sign is a function, on is a function, and if you look at the parameters that are being passed to the on call, there's three parameters being passed, one of which is a function that we passed in, it's a callback. Exactly like passing a callback into set timeout, or passing a callback into any other utility, we're passing a callback. We're asking for this callback to be invoked, to be run whenever somebody clicks on a link. It's not going to happen right away. They're going to wait a few seconds, and we want it to happen whenever it does. Okay, so go back here. Alright, so if we save this file, and we reload our page, do a refresh of our page, if I didn't mess something up, now when I click Login it pops up a modal with the login contents in it. Now I don't have any close buttons or whatever, we do that later in the exercise, so right now we just pop up a modal, but if I refresh, and obviously it refreshes the page and goes away, and if I click Register I get the register page loaded. So that's the step that you should be at is being able to load that content and put it in a modal. (Student) How do you spell propagation? P-r-o-p-a-g. The good news is, if this was complicated and you got lost or you feel a little bit intimidated by this, which is totally okay, the first time I saw code like this I was lost, trust me. If this is complicated to you, the good news is that this is about as complex as jQuery programming gets. I started you off with an example that kind of it shows a lot of different pieces moving in, pulling in an element from the DOM. That's what this first call is doing. This is pulling in an element from the DOM by its rel attribute, same thing we did with modal. Calling a method on that chain, calling .on and giving it several parameters, making an ajax call, setting the inner html of those contents, showing an element. This is basically like 80% of what people do with jQuery in this one little snippet. So even though it may feel like, wow, this is kind of like overwhelming or whatever, if you take some time to digest just this one file you've actually probably got the same amount of skills as like 50% of jQuery developers have, and the other thing to note is that we didn't do anything tricky with JavaScript itself. Ninety-nine percent of the complexity that we see in this file is jQuery related, not JavaScript related. So if you spend time to learn a tool like jQuery, like I've taken time to learn, then you can sling about the jQuery stuff, and it just works, and the same is true of JavaScript. If you learn the JavaScript fundamentals you can sling JavaScript around, and you won't get confused. So this is just another thing to learn, it's a jQuery library that's helpful. It makes --- the code didn't do this without jQuery would be worse, so even though that may look ugly it's better than it would have been. Question here. Why not using a,rel js-controls? You totally could have done it that way. I don't like to use tag names or ids. I try to avoid DOM specific things, like what tag name was used or whatever, so that's why I would avoid using a, but there's lots of different ways to use the jQuery API. This is just one of several. What else did you work on after header.js? I didn't. The only code that we've changed right now, so far, is header.js. Yep, header.js is all we touched. Okay, any questions here about stuff I can clear up for you? It would have been rather cruel of me to expect you to just know all this stuff, that's why I walked you through it. Fortunately, the next thing that I'm going to ask you to do is going to be a bit simpler. It's going to build off of some of this stuff, so you want to have your file in that state. If you don't want to retype all that stuff just copy and paste that whole file from over there, which is totally fine if you want to do it that way. Task 2 - Carousel Let's go back to our README. We've handled steps one, and two, and three of task one. Step four says, there's nothing else, so we're now complete with task one. Is there a way to exit the modal without using it? Now we don't have a way to exit it yet. We're going to come back to that later in our exercise today. Right now the modal, once it pops up, it stays there until we refresh the page, so we'll fix that later. So, task one a little overwhelming perhaps, but it really did start to show some practical application of the concepts that we were just foo barring earlier, so I hope that answered some questions that people had earlier. We'll be looking at more of those practical applications. That's the goal here. This part of the workshop is all about the practical applying, doing practical application of the concepts from earlier. So let's turn our attention now to task two. It says we need to open up carousel.js and details.js, and so I want you to go ahead and do those. I'm going to close out a few of these files that I don't need for right now. Like I don't need the styles.css. Let's close header for now. We don't even need that one. We'll come back to it. Let's open up carousel and details, and hopefully it will be clear fairly quickly that I've done a lot of the work already. I didn't want you to have to figure out all the math for how to do a left and right scroll or whatever. If you want to try your hand at it and challenge yourself you can delete my code and try it, but I've already provided you the math for how to do a scroll left and scroll right for a carousel. I've already set up all the stuff. At the very bottom here it says, you want to attach click handlers for the left, now $left is the left button, and the $right is the right button, so you just want to attach click handlers to them, and have those click handlers call the scrollLeft and the scrollRight functions that I've already written. So that's just two lines of code. That's going to be much, much more straightforward. The details one has slightly more work, but not a lot, and we'll come back to that. So let's look at the README. What does it tell us to do first? The first item, number two here, it says, in carousel.js add those event handlers for the left and right carousels. I'm going to do the first one for you, and then it'll be really easy for you to figure out the second one, okay? So I have a $left element, and I have a scrollLeft function, and I want to put those two together as a click handler. So all that's left, down here at the bottom, I'll take out those comments. To set up the left one I just say $left.on("click") and give it a callback. What's my callback? ScrollLeft, right? That's it. So super difficult task for you, do the one for scrollRight, and that should look like $right.on("click"),scrollRight. Okay, save that file. Let's refresh our page, let's see what kind of magic we now have access to. (Student) I'm nowhere near that fast at typing. Okay, sorry about that. (Multiple students talking) (Student) I'm sorry, did you pull all that out of the, out of the solution to paste in? No, no, no. This is the starting version of the file. The only two lines that I had to write in here were these two lines. (Student) I have only two lines in mine. (Student) You're looking at details. (Multiple Students Talking) (Student) Never mind. Yeah, there's a question in the chatroom, the callback goes without parentheses. Exactly. If we put parentheses here what would happen? It would call scrollLeft immediately, and the return value from that is what would get bound, which isn't a function, so that wouldn't help. So yeah, we definitely just pass it by name, okay? So now if we refresh the page we now have a silly, but working carousel. By the way, just as a little side note, I did have a slight amount of math, as you can see here, like figuring out to add plus and minus 250 in position, but you notice I'm not doing any work for animations, though when we run it, it is smoothly animated. The way I achieved that? CSS animations. So if you look at the CSS style sheet, sorry, CSS transition. If you look at the CSS style sheet it's so cool how easy this is. On the CSS style sheet the items element is the one that's moving around, and I just put a transition on it, which says, when I change the left property, instead of it happening immediately, I want it to take half a second, and this last parameter here is for easing, so that it looks a little smoother as it eases out and moves in, so one line of CSS instead of invoking some crazy JavaScript animation library, and it provided a nice, little, smooth movement for us. Like I said, that's the most proud I can be of CSS because that's about all I know. That's about the sum total of my CSS knowledge. Okay, so carousel, it's only 41 lines of code. We don't need complex plugins to do simple little tasks like what we're showing here. There are tens of thousands of great plugins out there in the jQuery world from everything that you can imagine, calendar widgets, there's about 100,000 different carousel plugins that you can get, and they're all much, much more complex with lots of extra features. I just prefer to approach everything that I do from the most basic and simple, and then work my way up. Instead of going and grabbing the most complex, crazy thing that I can, and dropping it in, and having to learn a whole crazy new API, it really just boiled down to, do I know how to do adding and subtracting of the number 250? That was about it. (Student) They're asking where that 250 came from? Trial and error. (Student) 250 pixels. My little icons are 200 pixels wide, and I have a 50 pixel padding between them, so that's it. Task 2 - Details Pane The work that we're going to do on the details pane is a little more complex than that one, but less complex than the header, okay? Check the README. What does it say to do? The README says, you want to set up an event handler that listens for clicks on items in the carousel, and whenever that carousel item is clicked you pull the id from its rel attribute and you do another ajax request to load it in, put its contents into the content div. Basically, it's going to be a lot like what we did in the header file, but maybe a little bit simpler. So essentially what I'm saying here is, we want to attach a click handler, so that when I click on one of these icons that click handler fires, it lets us know which icon we clicked on. When we go to the HTML you'll notice that each item in the carousel has its own number. It has an id basically. So we want to grab that number, and then that is the file that we want to ajax in. So if I click on the one that has -0 we want to load a file called 0.html, and if I click on -1 we load 1.html and so forth. Okay? So I'm going to get you started, and then I'll give you a minute, and see if you can figure out what to do from here. So I'm inside of the details folder. I mean I'm inside of the details file, and I already have set up for you references to the variables. There's an items element, and a content element, and those are the two that we are going to need, so I want to attach a click handler to the items element, so I will say, items.on. It's a click handler. I'm going to be delegating from the individual elements inside of it, so we come back to the index.html, and we'll notice that I'm delegating from elements that all have a rel that starts with that value. So I can say, rel, hat equals is the starts with, dollar sign equals is the exists in, either one of those will work, and I want to do an event handler. Now before I let you go on this task to try your next step I want to suggest that instead of doing these inline functions you pull that out as its own function declaration. This is a stylistic thing more than a functional thing. So give it a name like personClicked or iconClicked, and use that name as your event handler. Okay, so your next task, knowing which actual icon was clicked, how are you going to pull out that rel attribute. Try that. Try setting up your id value by pulling out that number from its rel attribute, and I'll give you 90 seconds to try your hand with that. There seems like there's some people in the chat room that are mentioning that they're struggling, stuff isn't working for them. I'd recommend opening up your console and seeing if there are JavaScript errors that are happening when you're doing stuff, like if you click a button and some kind of error happens here that's a problem. That could mean that we have a variable named incorrectly or something like that, so looking at your console while running things, if you see stuff just silently not working the way it's supposed to check to see if you're getting JavaScript errors, and that might be a place to look. Alright, so the step that I needed to do here was get the id of the person that was clicked on, right? So I can say var ID is equal to. Now event.target is the icon clicked on, so we can say, evt.target. Everybody with me? Now what do we want to do? We need to pull out its rel attribute? (Student) Yeah, .attr. .attr("rel"). Now that's going to give us the whole value. It's going to give us js-item-0, for example, and we only want that last little part, right? So there's a couple of different ways to do that, but the trick that I'll use is a regular expression, and you could also do substrings by looking at its index from the back or whatever, but there's a neat little trick with regular expressions where I can simply replace everything that isn't that final number with an empty string. So I can say replace. I see the question. I'll get to it in just a moment. I can do replace, everything from the beginning up until that final set of digits, which is \d, that comes at the end, and I can say, keep that thing by wrapping it in a parentheses, and everything else I'm going to get rid of. So if you don't speak regular expression don't feel bad. It took me a long time to learn it as well, but what I'm basically saying here is, start at the beginning of my string value. Dot means match any character, and star means keep going until I match something else. This parentheses set says I want to capture that thing, so I can keep it. \d is a decimal character, so it's one of the 0 through 9, and plus says I can have more than one of them, in case I had more items in my thing, and then what I'm replacing that whole match with is only what was inside the parentheses, so I'm basically ditching all the rest of the stuff. (Student) Kind of have to use your cursor to do that, so it will ---? Yeah, sorry. I always fall into that habit. Okay, so the hat symbol says, start at the beginning of the string, dot star means match everything until we get to some number characters, and then the end of our string, and then dollar sign one means pull in the stuff that was inside of this set of parentheses. Okay. Quick little tip about dealing with JavaScript debugging, if you're trying to verify that you got the correct id here. Most people do a console.log. That's the old school way of doing it. I'm going to show you a quick way of dealing with the debugger if you're using something like Chrome, and if you're not using Chrome Firefox does have one, but it's not as good right now, but there's a way to set a breakpoint, and we could do that in the editor, or we could do it in our code by typing the word debugger, so I'm just temporarily going to insert that word, and I want to verify that I'm in fact getting the correct id value, so I'm going to switch over, I'm going to open up my developer console. (Student) Should we save first? I thought I did save it. (Student) Oh maybe you did. I didn't see. Yeah it's saved. Okay, so I've got my developer console open here, and when I refresh the page, when I click on one of these items it's going to switch me into the debugger because it's going to catch that breakpoint that it runs across when it finds the debugger statement or it's going to give me an error here, so we know we have some sort of error. Alright, so unrecognized expression. Let's go back there and see what was I doing wrong. Oh, it's because I didn't end the bracket. Okay. Oops. Alright, let's try it again. Let's refresh the page, click on an icon. Now we're in interactive debugging mode inside of the developer tools, okay, and you'll notice that we are at this breakpoint, and one of the things that the breakpoint is showing me, if I collapse this one because I don't care about my call stack, you'll notice that it's showing me my local variables that currently exist. So I have a local variable called ID, and guess what, what's its value? It's one, which is what we expect. In a 0 based system I clicked on the second item, so I'm expecting to get ID 1. Now I could click it one more time just to verify that I get ID 2 or I could get ID 0, so I verified that my ID logic is correct. That was just a quick little glimpse at using the developer tools to your advantage instead of always falling back on console.log. Alright, let's take out the debugger. We don't need that there now. We verified that our ID statement's correct. Now what do we want to do with that id statement? We want to make an ajax call with it, right? That id.html is the file that we want to load, so remember we do ajax. What's our URL? ID + ".html". There's one additional detail here, which is that these files are actually in a subfolder called details, so we want to put that on the beginning. So that's the file we want to load. We need to give it a callback that is going to receive the contents. Actually, I'm sorry. That's not how jQuery works. It doesn't use the callback there. We have to pass that into the .then function. It's going to receive the contents. One other little thing, jQuery kind of is annoying that you have to tell it, don't parse anything, I want you to treat it as just text. So we say, dataType: "text" here. So, at this point in my code I should have a contents variable that has the contents of that HTML file. What do we do next? $content.html(contents). $content being the variable that's pointing at our details pane (Typing). Let me verify against the solutions folder, make sure I didn't mix that up somehow. I'm going to change it, just for the sake of future exercises. I'm going to change this to loadPerson because that's what I intended to call it, so instead of personClicked I'm going to call it loadPerson. So conceptually that should be all the steps that were necessary to let me click on an icon and load its contents into a div, so let's try it. Let's see if that works. I don't need my debug tools open. If I click on this icon, sure enough, it loaded the person in, and if I click that icon, and then that icon. Now I recognize that I already wrote a bunch of code for you, but the sanity check that I want to give you here is that we did not have to write more than seven, eight lines of code to wire ourselves up with a fairly interesting task that we click on an element, we pull out something about that element, we make an ajax request to a file system or to a URL to grab the contents of that file, and then we stuff it in an entirely different part of the page. We actually didn't have to do a lot of work to make that happen. And, as I said earlier, 99% of the work that we had to do was, well, maybe in this case a little less than 90% because we had regular expressions involved, but 80% of the work was just using the jQuery API, which you learn once, and then it's just a tool like any other hammer, you can swing it. Alright, any questions about task two? (Student) Did you get that one? Did I get what? (Student) That one question that --- What's the question? (Student) He was asking about that line, it's line 12 now. He's asking about this line. Yep, so each one of these, if I replace them just to simplify, because we know that those are just selecting elements in the page. What we're left with is an element, arrow, element, arrow, element. In CSS that little right hand arrow is direct descendant. So what I'm saying is, find this element, and then find its direct child, and then find its direct child, and those elements I'm specifying with those attribute things. So I'm saying, rel=js-carousel, js-content, js-items. Technically, I could have probably gotten away with doing just js-items, assuming, of course, that js-items is totally unique. Here I'm making it more unique. Theoretically I can have another js-item somewhere else in the page. I'm making it more unique by giving it a specific path. Modules Task 3 - Header Module Now task three, now that we've done some stuff with jQuery, we've gotten some things loaded up, task three then, what we want to turn our attention to is not adding new functionality to the app, but reorganizing the way the existing functionality is. So, if up to this point you've felt like, oh you're a little bit overwhelmed with the jQuery stuff or maybe your stuff is not working, I'm going to remind you that my best suggestion is for you to grab the contents of task two and just overwrite your files with all the contents of task two, so that you're in a clean, fresh environment because for task three I really do think this perhaps is one of the most important parts of all of the exercises that we've done is to get our heads around how to use organization techniques, like the module pattern, to arrange our code. So the first task here shows us that we have --- it tells us to open up these three files, and we want to use the module pattern to expose a module for each one of those files. So I'm going to do the first file, and then I'm going to leave you maybe 10 minutes or so for you to work on the second and the third files, and you'll do exactly the same things, so it'll be the same pattern, but I'm going to let you --- I'll show you how we do it the first one, and then I'll let you. So let's work on the header. I'll open up back up header.js, and I'll do header, and then you can do the carousel and the details ones, okay? Again, we're not going to add any new functionality. We're just going to reorganize this functionality. So the observation that we can make about header.js is that all of this stuff that we see here is happening out in the global scope. There's a document ready that's happening in the global scope. If the document ready wasn't there this variable would be a global variable. That's the sort of code smell that we want to try to avoid because there's no organization around this at all. It's just in its own separate file, but beyond that there's no nice, clean interface for it. It could have an accidental overlap with other functions and variables and things like that, so we typically want to avoid, as much as possible, any kind of stuff happening out in the global scope, which is one of the really best benefits of the module pattern, is how easy, you'll see in just a moment, how easy it is for us to take what we would call just sort of global, blah, spaghetti code and reform it into something that's more well defined. That's really the main point of the module pattern. So I'm going to do this file, and then you take over and do the other two, okay? The first thing that we want is we're going to want a thing to represent our module, a variable, so I'm going to call my capital H Header. Now I'm going to wrap a function around all the contents of what's happening here as my first step, and the interesting thing about doing that though is that I've wrapped a function around it, but that function has not run yet, okay? It's just a function that's wrapped, but if we want that function to execute we actually need to execute that function expression, which the most common way of doing that, we didn't go over this explicitly, it's covered in the book, is to put a set of parentheses around that, and then another parentheses set on the end, and that final parentheses set down there is the most critical part because that actually executes our function, and this pattern, by the way, if you're doing Google searching or looking in the book, this is called the IIFE pattern, I-I-F-E. IIFE stands for Immediately Invoked Function Expression. We're a super creative bunch in the JavaScript world. We come up with really creative names for stuff. It's a function expression that we immediately invoke. So we call it the IIFE, okay? So I've got an IIFE, a function that wraps around and runs stuff. Now, inside of it I don't want this document ready stuff here, so I'm going to take, temporarily, I'm going to take the document ready part, and I'm going to move it outside of my module, and we'll come back to that in a minute, okay? So I'll take that one, and that one, put those down here. We'll come back to those in a little bit. Now this code, if we tried to define, what is this code doing, it's essentially the initialization code for our header module, right? So we could take function init, call it init, and wrap a function declaration around all of that code. Everybody follow that? And then we could observe that we've got an inline function here, which isn't really buying us anything, it's actually more complex to look at the code that way, so I'm going to take that function and not make it be callback expression. I'm going to move it out and have it be its own separate function, which I might call headerLinkClicks. Just making up names at this point, okay? So that code I'll put in here (Typing). So this is my init function, and I need to call, what did I call that function? HeaderLinkClicks. That's the name I need to pass for my callback. Now this modal variable you can see it's being declared inside of init, but it's now being used in a different function. Can everybody see why that would be a problem? It's being used inside of the header links, headerLinkClicks function, but it's only being declared inside of init. There's a simple fix. Take the var part out, and instead make it something that's available to all the functions here by making it a module level variable declaration. Still assign it inside of here, but now when I declare it there now it's available to all of my inner functions. Questions on that? Do you see how that works, how that part works? Now the last step is that this module needs a public API, right? So I need to do a return statement with an object, and what do I need to put on my public API? I need to put a reference to that init function. Does that look familiar from the stuff that we did about an hour or two ago, we did earlier this afternoon after the lunch break? We have inner stuff, these inner functions and inner variables, and here is where we declare our public API. So the thing I want you to get, and I'm again, use the trick of code folding to make this more visible to you. I'm going to take that internal code, just temporarily, I'm going to code fold it, so you don't have to look at it, and what I want you to see here is that header is now going to reference that object that we returned. Does everybody see that part? That object that we returned gets assigned to a variable called Header, which means on the outside what can we do? We can call header.init, right? which is what we want to pass to document.ready. We just want to pass a reference to the Header.init function. Remember, I'm not calling init, so I'm not putting the parentheses here. I'm just passing a reference to the function, so that jQuery will run it later. Kevin's asking a question, versus the other way shown earlier. Can you be more clear on what other way you're talking about? Okay, if I save this file, which I will, and I rerun my program, I just refresh my page and verify that my register link still works correctly, and my login link still works correctly, that means I didn't change any of my functionality. All I did was improve the style of my code. Let's make some observations about the style of my code. These functions no longer have any potential to be public. These functions are now hidden privately, and the only thing that gets exposed is this function, the init function. We expose that publicly, but the var modal variable it's not exposed publicly, it's hidden as a detail inside of the module. Ah, so the question in the chat room is, in an earlier version today you might remember that I just did something like function Header or we called it function Hello earlier, and instead of having that stuff down at the bottom it was just a normal function, and you might remember that I did something like o = Hello from earlier. So what I'm doing is combining those two things into one step. Instead of declaring a function, and then calling it once, if I only need one of it it's basically a singleton. If I only need one of it I'm just combining those two steps instead of declaring one and then calling it. I'm using the IIFE to declare and call it all in one step. Task 3 - Carousel and Details Modules Armed with that as our header.js, I want you to do the exact same thing for the carousel file and for the details file, okay? Same mindset, same process, same syntax, but it gives you some practice doing a real world module. If you have been feeling like, wow, this is bending my brain a little bit or I'm not quite --- this is the most important of any of the exercises that I've given you today is to try your hand at it. Try your hand at doing what I just did on header.js, try doing that on the details.js or the carousel.js because, as I said earlier, there's value in the confusion because when you work through the confusion, and you have the lightbulb moment and it works that solidifies it way more than anything that I could give you as a lecture. So I will give you about 8 or 9 minutes or so. We'll come back, and I will talk you through how I do that conversion carousel.js, but try your hand at converting both of those to modules. So I have zoomed way out, so you could see it all at once, but the major patterns to be looking for, if I can use some folding magic here to kind of keep the unnecessary details away from us. The major details to look for are an outer function, which needs to run at least once. Here we only need it to run once because we only need one header instance. If we made it a regular function we could call it multiple times and get multiple modules, but we need it to run at least once, and we need to have some private stuff. So we've got some private variables and private functions in here, and then we need to have a public API that gets returned back, and that's what gets assigned to our instance variable. That pattern of doing modularization is essentially identical to every module I've ever written. Like there's little tweaks and bits and pieces of things that we do sometimes differently, but the basic concept there is an outer function with inner private functions and variables, return an object that's a public API, and that's really it. So while we can get overwhelmed a little bit sometimes in the weeds with jQuery syntax and stuff don't miss the bigger picture here, which is that this pattern is about code organization. If I gave you just a bunch of simple foo bar examples you don't really pick up on why this module pattern is so useful, so I have to give you a somewhat more complex app that's got some of these other moving parts in it for you to really pick up on why that is an improvement over what we had before. Okay, so let's quickly try our hand at it. I'll start with the details one. Let's quickly try our hand at, we need a var Details, we'll use another IIFE because we only need one of them. I'll take the ready thing out for right now. We'll put that at the bottom. There's my IIFE closed. Here's my internal private module function called loadPerson. Here is my init code, essentially. This stuff is what I'd wrap in an init function, and then I'd notice right away that I'm going to need those variables across multiple functions, so I want to take those vars out basically, and put them at the module level, so I need var items and var content, and then what's the next missing piece? I need a public API, right? So what's my public API? Init: init. And now on the outside we have Details.init. Do you see how that was the exact same pattern as what I did in the previous file. This is one of the most useful hammers that you can have in your toolbox. You're going to pull it out all the time. Bam. Bam. Just hammer the nail everywhere that you see some code organization, module is probably going to be your first, should be your first instinct. Oh, I should use a module to organize that code. Okay, so with that out of the way let's try the last one, the carousel. Oh, there's a question. We moved the var declarations out, but the question is, why are these in there? We can't run this code until we're sure that the DOM is ready, so we leave the initialization of those variables in the init, but outside of init we have the declaration, so that we can share those variables across all of our internal functions. Sorry. Init is shorthand for initialize. It's just the common name that people refer to, the kind of first initialization step of any entity. Okay, I had renamed personClicked back to loadPerson, so it's still there, it's still inside of our module. The question was, what happened to personClicked? I had removed person --- I had renamed personClicked to loadPerson in an earlier session. Okay, so let's switch to carousel. Same basic principle. Var Carousel, put in an IIFE. Take the, oh I didn't even have a doc --- oh there it is. I was like, where's my document ready? Take the document ready out, move it outside. These are all fine as private, internal functions. That's good. These are all things that are going to need to be inside of an init function, but those declarations need to come out, so I'm going to take all those vars out. Those need to be at the module level, so that they can be shared with the other functions in the module. So I'm just going to have one big var list of those (Typing). What do I need next? (Student) Return the API. We need an API, right? Public API. (Student) Yes. Either I've completely lost you or we've run out of coffee or both. Are people following along? Yell at me if I'm going too quick. (Student) Yes. Are we following it? (Student) Yes. Okay, so init: init. Now what do we put down here inside of the document ready call? (Student) What the name of the function was. Multiple students speaking. (Student) The module's carousel, right? That's the carousel --- Module Carousel.init. Task 3 - Questions Question was, why are we organizing things into modules? (Student) To hide the internal stuff. So the major reason for organizing things into modules is if you zoom out and you don't pay any attention to those internal details, or if you code fold, and you ignore the internal details the major thing here is that we are able to declare private internal details. That's a function, that's a function. We've got a bunch of private internal variables. We don't want to expose that stuff to the outside world. If that stuff was global variables or global functions there's an extremely high chance that some other file, also declaring global variables or global functions, could accidentally override or collide with one of ours. So we don't want global variables because of the high chance of collision, the high chance of accidentally overriding variables that we weren't intending to. Those are all negatives in code, and that's what most people refer to as kind of the wild wild west spaghetti coding of JavaScript. That's where everybody starts. We all start by, as we're learning, we start putting stuff in the global scope, but the next step of maturity is to say, I don't want to put that stuff in the global scope, I want to wrap it up inside of a module. So I put this stuff inside of a module, and then only the stuff that's public needs to be public. So here that Carousel.init is the only thing that needed to be public. All the rest of these details, these functions and variables, all that stuff is private, and there's no reason to expose it to give us the potential for collision. The primary principle here is that modules give us encapsulation, which is a fancy $25 word for saying private, private stuff. Leslie asked, in most cases will our return be init: init? Well, I've set up this example that we're going through, this exercise today, artificially to look like that. Most of my modules have several methods on the API, but our simple example that we're going through here is just focusing on keeping as much stuff private as possible, so we aren't seeing any examples yet, although we will, we're not seeing any examples yet of any need for other public API stuff. Question says, this closure pattern looks for me --- looks to me like declaring a class. What's the main difference? Does a class handle the DOM and jQuery? So there's a bunch of different stuff in that question that we don't want to mix up. This code organization decision about whether we use a module or whether we try to implement something that looks like classes has absolutely nothing to do with what we're dealing with in the DOM or CSS or any of that stuff. It doesn't deal with jQuery or whatever. It's really just a question of how do we organize our functions and variables. It's at the JavaScript level that we're asking this question. It doesn't matter what we put on top of it. So at the JavaScript level if the question is, is the module my better hammer or is the class thing that people try to do in JavaScript my better hammer? And I could make a dozen different observations about differences, but the major one that I'll make an observation about here is that the thing that people call classes in JavaScript does not offer any notion of privacy. Everything in a "class" in JavaScript is public. By default, everything in a module, as we're seeing here, is private, and you get to decide what to make public. So that's the first, probably biggest, observation that I could make about the differences, although there are dozens of other differences that we could go into. There's some comments being made about, it's not really classical inheritance. Yeah, I'm not a class fan at all. I don't like classes, I definitely don't like them for JavaScript because JavaScript doesn't really actually have classes, and I do in my advanced course, as well as in my Object Prototypes book, I do go through what I call classless objects. It's a way of defining objects and using prototype delegation without the notion of classes at all. I think that's a much better way of going about it. The little catch phrase that I have for it instead of OO, which is what people mean when they say object-oriented programming, instead of OO I coined the phrase OLOO, O-L-O-O, which stands for objects linked to other objects. So there's a pattern for dealing with objects that doesn't bring any of the complexity of classes into it. A question was asked, what scenarios make sense to ever pass in a parameter to an IIFE? That's a great question. It's outside of our exercise, but it's a good enough question. Let me take a quick little side note. So set our exercise aside for just a moment. Let's pretend you're not even going to deal with a module design. You just have a bunch of stuff in a file, a bunch of random functions and variables in a file, and you want to organize that file, so that that stuff isn't global. Well, the easiest way to do that is to have an IIFE wrapping around the entire contents of your file. So you start the IIFE at the top, you end the IIFE at the bottom, and all of your spaghetti goes here, okay? And in the early days of me learning JavaScript, this was the most important thing I did was just go through and find all of my files that I had a bunch of global stuff, and wrap an IIFE around the entire contents of the file, so that that stuff's private inside of a function instead of public. Now some stuff needs to be public, otherwise there would be no point to any of the contents of that file. If none of it's being accessed anywhere, then that whole file is pointless, and you should just delete it. So let's imagine that I have 100 different variables and functions, and I wrap a big IIFE around all the contents in that file, and then I try to run my program, and I notice that 2 of them are breaking. The other 98 of them aren't ever accessed anywhere else. Well, what I've concluded then, is that I've got 98 things which ought to be private, and two things which ought to be public. This isn't even asking the question about modules, it's just asking a question about access of variables. So let's imagine I had 98 private things here, and I just leave those 98 private things completely alone, alright? The two things that did need to be made public, I could easily make them public by just simply adding them as references on the window object. So I could say something, if there was a thing called foo in here, and I needed to make that public, I could say window.foo = foo, and if there was another one called bar I could say window.bar = bar. That makes references on the global object to these internal private things, and that makes them accessible to the outside world, just like they were before. So 98 --- different things stay private, these things get public, and now the question back at hand was, what scenarios would I ever pass something into an IIFE? Well here's where I would do it. Because an IIFE is just a regular function call, I can pass stuff in. So I could pass the window object in, but stylistically I don't like using the window object name. It doesn't really speak to me from a JavaScript perspective. It's a DOM thing, but it's not a JavaScript thing. From a JavaScript perspective I'd like to give it the name global. So if I have a parameter name of global, and I pass window in as an argument to it, essentially global becomes an alias for the window object, and now inside of my code, anywhere that I need to do global stuff I use the word global instead of the word window. This is purely a stylistic thing, but there what that does for me is it now lets me visually see the stuff that's global, publicly available, versus the stuff that stays private. If I see the word global anywhere I know that, that jumps out at me as a big neon sign that stuff is public. Finally, I would mention that especially in the jQuery world, when people deal with multiple frameworks being on a page, it's very common for somebody to say, well, I've got some stuff from jQuery that I want, some stuff from prototypes, some stuff from Dojo, whatever, and they pull in a bunch of different frameworks, and the problem is that most of those libraries and frameworks try to use the same dollar sign symbol for their main function, which is pretty annoying, and it means that dollar sign essentially becomes unusable because you don't know who was the last one to point to it, and so a way to solve that is to pass in the jQuery object, for example, by name. Of course, I never want to type j capital Q Query. That is like the worst variable name ever invented. I don't want to type that because I'm going to mess up the capitalization 1000 times in my code, but if I pass it once by name, and I give the parameter alias dollar sign, now inside of this IIFE, from lines 2 through 9, all of these hundreds of functions can use dollar sign reliably because we know for sure that inside of this IIFE dollar sign always points at jQuery. Those are the two major reasons why I pass stuff into IIFEs, so hopefully that answers that question. Next question. To what extend is document ready necessary, just a good practice? That is a really good question. So you'll notice that I am using document ready all over the place. There's an awful lot of information out there on the web which says, if you put your script tags at the bottom of your body, which I have done here, there's a lot of people out there on the web that claim you don't need a document ready event because by the time your script runs your document's already done parsing. That's the claim. That claim is false, even though most of the time it accidentally turns out to be true. Technically, the DOM is not necessarily guaranteed to be complete, even though many times it often is complete. So basically what I suggest is, don't assume anything. The reason the document ready event exists, its sole reason for existence, is to allow you to wait until you're sure that the document is ready. That's why it's called that, so don't assume that it's ready until that event has fired. As a side note on that, there's an awful lot of stuff that we do in our apps that doesn't care about the DOM, and people still wrap that stuff up in a document ready, which is kind of an anti-pattern actually. You're waiting unnecessarily. For example, let's say you need to make an ajax call. Ajax doesn't deal with the DOM at all. There's no reason to put an ajax call inside of a document ready handler, although that's where most people do it. So document ready, specifically, is for any piece logic that actually deals with the DOM, because if the DOM's not ready you're playing wild wild west games, risking whether or not you can use it or not. Hopefully that answered that. Next question, the code we covered today is compatible with all browsers, including ---. Yep, absolutely. Everything I'm talking about is straight up simple JavaScript. We're not talking about any complex patterns that are like ES6 or anything like that. Okay, can we use objects as a parameter, and then pass parameter as a property to the object? Yeah, absolutely. So the question is, can I do something like if I have a function called foo, and he takes some o parameter, and I call foo with an object, can I pass in an object like that and reference that? Yeah, absolutely can. I can say o.name, and that'll print out Kyle. Kevin's saying that document ready is the same thing as DOM content loaded. Absolutely. Document ready right now what it does is it waits to see if that event is fired, so they are synonymous for our purposes. Okay, great questions by the way. Thanks for asking all those. Yeah, you can listen for DOM content loaded by doing window.adamentlistener, absolutely. Okay, back to, mental context switch back to our exercise. We're not complete with task three yet, but we have made significant progress on task three. Are there any questions so far on task three? (Student) In this case particularly, when we (Inaudible) are other functions within like function.predicate (Inaudible) this case, so there is no global variables getting exposed right here. The only global variable is this variable. (Student) No, not --- We're essentially treating these variables like namespaces. (Student) The way we wrote initiate. Oh, when everything was inside of a document ready? (Student) Um hmm. At that time, if everything's inside of a document ready it's also private, except for the fact that most of that stuff shouldn't have been in a document ready. That was the point that I made. That's sort of the orthogonal point that I made, which is you don't want to put all of that stuff in a document ready, so if we had just said, I'm not even going to use modules, but I just want to refactor that original code to only put stuff there that's necessary, then we would have been taking a bunch of variables and functions and putting them out in the global scope. That'd have been the only place to put them. (Student) But like we wrap everything inside of functions, right? Like when we declare it inside a function it just, it will be part of that functions code, right? Well, what I'm suggesting to you is this. Let me open up the solutions folder back for task one. In this code not all of the stuff inside of here should be, like we have one thing that's outside, this version of the file didn't have the document ready, right? So if this had had the document ready like it should have, it should have said this. (Student) In this code now when like we write like this everything is function scoped within that function. That is true, but the point I'm trying to make is that most of this stuff, well not most of it, but some of this stuff doesn't need to be inside of a document ready. This whole function thing here doesn't need to be inside of a document ready because it's not going to be called until long after the document's already ready. So if I had approached this file not from, first make it into a module, but just don't put stuff in DOM ready that you shouldn't, the first step that I would've done is to take that function and move it out of the document ready because that's the more proper place for it, right? Now it's a function outside that I reference by name, and now we're faced with this same problem that I got us to. So I just combined both steps into one rather than doing them separately, but we come to the same conclusion, which is I don't want all that stuff in the global scope. It's a good question, but I just want to make sure you understand I just did both steps at once. That make sense? Okay. Task 3 - Refactoring Details and Carousel Let's look at step three. I want you to observe something. Again, we're kind of trying to take a higher level view of what's happening here in this code, okay? So don't get too much focused on the syntax, and let's think more about conceptuals. What does the details.js, what does the details module signify to you? What is its job? (Student) Display details. Display details, but really more just to manage the details pane, right? What is the carousel modules job? (Student) Manage the carousel. To manage the carousel, right? So would you consider it to be kind of a weird code organization if the carousel module had details specific code inside of it? (Student) Yes. That would look weird to have, if we're going to all the trouble to have separate modules we want them to be independent, right? Same question. If I had carousel specific code inside of my details module that would equally seem not appropriate, would seem like too much mixture of the two, right? If we're properly structuring our modules we want to put code where it belongs, is the point I'm making. So let's go back to our code and see the current state of things. Do you see anything inside of the details folder that looks like it's directly related to the carousel? (Student) We're searching for the --- (Student) Items. Basically all of init. (Student) Yeah. Most, or these two lines, two of the three lines in init are related to the carousel, but we're dealing with them inside of the details module. The point I'm making is that even though this function, even though this code is functional, it gets the job done, it's kind of not organized well. It would be better if we could figure out a way to take the carousel specific code and keep it entirely within the carousel module, and keep the details code entirely within the details module. So this next step of task three is to observe that that code belongs over in the carousel module. So the first thing I'm just going to do is take those two pieces of code, I'm going to copy them, delete them, and I'm going to move over to the carousel module, and I'm going to put them in here, down here at the bottom. Just my first step of figuring out how to organize, because this is really where those belong, okay? Now, one thing right off the bat that I'll notice, which actually should have been a good clue to us, remember how I just moved in this items variable? We already have one. We're already getting the items variable, so we don't need this items variable anymore at all. That one is superfluous and unnecessary, which is a clue to us that it was not in the right place to begin with if we had to do that lookup twice. Does everybody see that? So that should have jumped out at us before, but now that we're focusing on the right things, now we'll look at this and say, oh, okay, so that stuff, I didn't even need it, but I do use the items thing to make my click handler. Now I do have this problem, which is that the loadPerson function doesn't exist in this module. Where does it exist? (Student) Details. (Student) Details. It exists in details, right? (Student) You just have to put a --- Alright, now let's look inside of details and see, is any of this code related to the carousel? Any of this stuff inside of loadPerson, is that related to the carousel? I would suggest that line four is pretty heavily related to the carousel because we're looking specifically at a rel attribute of an item that it sits inside of the carousel. (Student) Yes. Does everybody see that? So line four also looks to me to be a line that should move out, so I'm going to take it out for right now. Okay? And I want to put it over here in the carousel, and I've got to figure out, where am I going to put it? Well, I need a function to go in place of loadPerson, so why don't I call this one clickPerson, and the name here is important because I'm suggesting that the carousel module does not actually care what happens after you click the person. That capability, that concern, belongs to the details module. The carousel just says, I just need you to be able to click something. I don't care what you do with it after that. Does everybody see that concept that I'm trying to get at? So let's call it clickPerson, because that actually signifies more directly what it's supposed to do. It is an event handler, clickPerson is an event handler, and that line of code needs to go right here. Is everybody with me on that? And let's take that named function and use that in place of code. So we've got it now in place of loadPerson. Now if we just left the code like this nothing would happen, right? We'd pull out the id, but nothing would happen over there in that other module. The details module wouldn't actually do the loading. So let's consider what's happening over here in the details module. There's no more event, so this is not an event handler anymore, but what does this function primarily depend upon? There's one piece of information that it needs. (Student) ID. Does everybody see that? It needs an ID. We've taken things where previously we had two different concerns packed together in the same function, we've now split them out into two separate functions, and separated them into two entirely different modules. That's a process that we call abstraction in programming, okay? So here I have a loadPerson function that I should be able to call with any id. It doesn't matter where the id comes from does it? I mean, I could just call loadPerson three, and I would want it to load up the third person. So from the perspective of the details module, he doesn't care at all where it comes from, and from the perspective of the carousel, he doesn't care at all what you do with the click. So we can simply delegate that behavior by putting loadPerson on our public API. So if I put loadPerson on the public API for the details module it means I'm not dealing with an event handler at all. I don't care where the loadPerson call comes from. It cloud come from a click event, it could come from an ajax call. I don't care. It just comes from somewhere, so you just call loadPerson. That's my perspective in the details module. In the carousel module I only care that you should load a person, but I don't care how that happens. I don't care about any of those details. So here what am I going to do? I'm going to call Details.loadPerson, and what do I need to pass to it? (Student) The ID. The ID that I calculated. Way more important than the syntax of what I just did is the concept of what I just did. Looking at a piece of code and analyzing, is this piece of code in the correct location? Maybe one of the most important skills that you can have as a developer in any language, but definitely in JavaScript. Looking at a piece of code and identifying, is this properly organized? Does it make sense for that piece of code to go here? It might be, and listen to me, it might be easier for it to be there, but it might be conceptually wrong for it to be there. In fact, I would suggest, in my career, been at this about 15 years, far more often than it ought to be, the easy spot is the wrong spot. Being able to look at a piece of code and think critically, does it make sense conceptually for that thing to be here? That's the organization skill that we're talking about. So what did I use to my advantage? Well, I used the idea that I know how to declare a function. I used the idea that I know how to call a function, and importantly to our discussion, I used the idea that I know how easy it is to expose something on my public API. (Student) Just one thing on line 14. We don't need items anymore on details, right? It's not used anywhere in the --- That's correct. Yep, we're not using items anymore, so I can take that declaration out. Good catch. Alright, just to make sure I didn't mess something up, let's test it. Test our code. Should, we're not adding any new functionality, we're just improving the organization. Should still be able to click these and load them. This is a rabbit hole that could go way deeper in a normal application. I set this up that that's the end of the rabbit hole in that particular case because we've done basically the practical amount of refactoring that's necessary. You could do more refactoring, but you're not going to get as much of a payoff for it, as we just saw there with them moving. So I artificially constructed this problem so that you could see the solution, and why the solution is useful, but it's way more important that you understand how I did that than what I did. How I thought about it, the questions that I asked, the tools that I pulled out of my toolbox to make that happen. Maybe the most important thing I teach you all day long is that thinking, okay? Task 3 - app.js Let's come back to our README. Let's check and see. So item number four suggested that we do exactly what I just talked you through. There's one last item. This, hopefully, is a much easier thing to get your brain around, but there's one last item to task three. It says, refactor so there's only one jQuery documents ready event, and it should call the init method of each of the three modules. It suggests here that we want to add a new file. So I'm going to create a new file, I'm going to call it, for my purposes, app.js. It should have a document ready event in it. Now inside of this code I want to call all three of the initialization methods for all of my modules. So I have Header.init, and I do need the parentheses here because I'm calling the functions. What's the next one I need? (Student) Carousel. (Student) Carousel. Carousel.init. (Student) And then details. And Details.init. That wasn't that hard, right? The last step, then, is to go back to those other modules and take out that superfluous document ready that was hanging out at the bottom of each of those files. Does everybody see how I did that? Oh, one last step. I need to actually load app.js, so I need to add a script tag in here. Now you'll notice that small little detail. This one needs to run, we need to be sure that this one runs after these things have been loaded. So just to be really, really sure that that's going to happen, it's not technically a big deal, but just to be really, really sure I'm going to put it at the end of my script tags list, so app.js. Let's double-check our work. Make sure that task three is still completely functioning. Uh oh. I did break something. What did I break? (Student) Didn't save something. Did I save it to the wrong location? I probably saved it to the wrong location. Save As. Yep, I was supposed to save it in the js folder. Haha. Okay, so I made the mistake, saved it to the wrong location. Now I've saved it to the correct location. Hopefully, yep, app loads, so now this should work. The question was, does that order ever matter? Sometimes. Sometimes the order of things that get loaded matters because JavaScript will run those programs in the order that they are listed. Task 4 - Event Emitters Just for the sake of keeping going along the same lines of thinking that we had before, I'm going to skip items one and two in the task four. I'll come back at the very end and do those quickly. Those are kind of some throw away things for you to try, but three and four are really spot on to what we were just talking about. So I already showed you that we could refactor to add an API method, which was this loadPerson method, to our API, and then we could directly call it from inside of the carousel function, okay? There's a couple of problems with that when you start thinking at an even bigger level, at an even higher level of abstraction, so we certainly improved things by doing that compared to what we had before, but even this may not be the end goal or the best possible design, so this next line of thinking is an even further stretch of your envelope, conceptually speaking, okay? One of the things that we've done here is that even though we have the two actual pieces of logic separate, we've created a very strong tie between these two modules, and we only have one of them, so it doesn't seem like such a big deal, but if the carousel module had 15 different functions in it, and it was calling 5 or 10 public API methods on the details module, and if the details module was calling the carousel module in a bunch of different ways there's an awful lot of spaghetti mixture that would be happening between the two. That design is certainly functional, and that's what most people think constitutes proper software design. My feeling is, it's functional, but it's not ideal. I don't like those strong, brittle ties with things. The carousel module should, to the extent possible, be completely independent from the details module. It should know as little as possible about the details module. In fact, it'd be good if it didn't know about it at all. That seems like an anachronism. It seems like it's impossible for the carousel module to call the details module or to invoke some of it's behavior, and simultaneously not know about the module at all. It seems impossible, right? It turns out that in software design, especially in JavaScript, we do have, I'm not going to call it like a silver magic bullet or anything, but we do have a way to accomplish to square those two things together. We can create a layer of indirection, which allows the two things to stay separate without knowing about each other, but still communicate, and the most natural way to do that is through events. Now you've probably picked up on the fact that we've been dealing with events like clicking on buttons, right? I click on a button that fires an event that I can listen to, but another way of thinking about it is, what if I don't have DOM elements at all involved? What if I just have two random JavaScript objects in my app, two different modules, and they don't know about each other, but they do need to cooperate to get the job done? Could I create a layer of indirection between them with an event system, such that this guy over here could send out an event, doesn't care who captures the event, and this guy over here could listen for the event, doesn't care who sent it. Do you see how that would create this sort of triangular layer of indirection, where they don't have to know about each other, but they still are able to talk through this intermediary, and what I've just described, this idea of sending out an event, aka publishing an event, and listening for an event, aka subscribing to an event, if you've been around at all in the development industry and web industry for a little while you may have heard a few years back PubSub. It was a big, hot buzzword that was going around, and people were creating companies for PubSubing and frameworks, and all kinds of crazy things, and there were books written about it, and all of that nonsense boils down to, do I have an object that can listen for events and send events? Like, you can take all of that nonsense that was going on for two or three years and boil it down to a centralized object that can emit events and listen for events. So I could create one of those really easily. If I could do that I could create a layer of indirection between all of my modules, so that they didn't have to know about each other, and that's what we're going to get at. That's kind of the final thing that we want to spend our time looking at. So I have provided to you, I have included to you a file called eventemitter2.js. We're not loading it yet, but we're going to load it now. So I'm going to add it to my list, so script src js/eventemitter2. That's one of those cans where the label tells you exactly what it's doing on the inside of the box. That thing creates something that let's us make event emitters. It's a tiny little library, like really tiny, but the great part about it is it is the exact same API as how events work in the node world on the server. It literally took the eventemitter API, they added some extra stuff to it, but they took the eventemitter API, and they ported it, so that it could be used in the browser as well, and when we talk tomorrow afternoon, if any of you come tomorrow afternoon, we talk about kind of the final arc of all this discussion. We talk about sharing code between things. That holy grail of sharing code is when I don't even have to switch. I can just use the exact same code in both places. So what's nice about event emitters, I can write the same code, and it'll run identically, no matter what the environment. For our purposes, it's just a tiny library that lets us do PubSub without any need for a crazy framework, or service, or an app, or book, or you know. We don't need any of that. We just, we need an object that we can send events to and listen to events. So here's how we use eventemitter. Let's go back to our app.js, and let's make an event object. I'll put it on the window, so that it's going to be available to everybody. So this is a global variable that everybody can access. I'll call it EVT, just that's my normal style of how I do it. So I'll call an EVT, and it needs to be an event emitter, so I'm just going to say new EventEmitter2, because event emitter is the constructor for this kind of object. We haven't dealt with what new does. Just don't worry about that detail. It's constructing something. So that thing is a thing that I can use in multiple places now, so let's go back to the code where I can calling .loadPerson. If I could think about that in terms of not telling you exactly what I want to do, but describing abstractly or indirectly what I hope would happen I would, instead of calling this a loadPerson I would call this event that has happened person-selected because I don't care what happens when a person gets selected from the abstract perspective, from the conceptual perspective. I don't care what you do with it. I just want to let you know that a person has been selected. So if I did EVT.emit, which is how you send events, and I used, I just make up an event name like person-selected, and I need to give it some data. The only piece of data that I need to pass along is the id. So we've taken one line and replaced it with that other line. I'm now sending out an event called person-selected, and I do not care who, if anyone, listens to the event. It's completely, I don't even know that there is somebody that cares about the event, but I just want to let people know just in case anybody --- cared. Here's an important detail. What if there was more than one different part of the application that cared? That's totally cool with me. I don't care. If there were 15 different parts of the application that each had a special, different job to do once a person was selected that's cool with me, because I just send out the event to the hub, and I let the other people deal with it, okay? It's an extra layer of indirection here. Now, how do I use that on the details side? Well, I come to the details module, and I need to listen for that event. Good thing to do in my init function. I'm going to listen, EVT.on is how we listen, for the person-selected event, and I need to have it call a function. Anybody have any guess as to what function I want it to call? (Student) LoadPerson. LoadPerson. That's cool, right? I don't even need to make a new function. Let's just call loadPerson. it's nice and convenient that it happens to be passing along the data to me that I'm going to receive from that event. Do you see how easy that was to actually create a full layer of abstraction or indirection between the two? Now neither one of the two knows about the other one. They don't need to, and because I've done that I've made my code significantly more flexible. You know what my favorite trick is when I deal with stuff like events? Now I can independently test these two modules. I can create a test mock that creates a fake event called person-selected. It doesn't wait for somebody to click a button. I just make a person event, and I throw out a piece of data, and I test whether or not the details module receives that event and does what he needs to. Because I have that layer of indirection I don't have to manually call a thing, I can just throw out events, or I can test the carousel module by setting up a listener to see if that event gets fired, and see if the carousel does his job. So events create that abstraction, which lets me have a lot more flexibility, a lot less rigidity to my design, more flexible for testing, and so forth. I'm a huge fan of this approach to software design. I don't like having one module calling another. Wherever possible, if I can avoid it, I try to avoid that. It's not always possible, but where possible, if I can avoid it, if it's just like a throwing the thing over the fence sort of an action, and I don't really need a response back, I just publish an event. Task 4 - Initializing Modules That's not the only place that we can use events. What about our init function? We're manually calling that init function from inside of our app. What if we took window.event --- I actually didn't even need to put that in the jQuery thing because it's not related to the DOM at all. What if we took this code that's inside of document.ready, and instead of calling header.init, and carousel.init, and whatever, what if we just published an event that people could listen to? Like, for example, EVT.emit("init")? That's a good event name. Now I have absolutely no idea what other modules are on the page. I don't care if they're there or not. I'm just going to throw out the event, and inside of each one of my modules instead of needing, I don't even need this method to be on a public API anymore, I can leave it there just for simplicity, but it's not even needed anymore. Inside of this code, not inside of my init, but inside of my module instantiation I just need to listen for the init event. EVT.on("init"), and what function do I call? The init function. (Typing) One little minute detail here. Now that app.js is creating this variable that the other modules need to know about, app.js definitely needs to be the thing to load before the other modules load, okay? So small little detail here, we need to make sure to move app.js up, so that it loads and runs before the other modules. Let's test my work. Let's see if I got it correct. Question. EVT is kind of a reactive program. Eh, reactive programming means a whole other umbrella of stuff. It's event-based programming. It's called event driven architecture or event-oriented architecture. Events are like a small little part of what reactive programming means. So there's a very, very small, tenuous relationship between the two. Okay? My code still works, but now it's using events instead of being directly called. Here's my last thing I'm going to finish up, and then we're done. I want to show you the power of using these events. Let's open up one of those details files. Let's open up 2.html, for example. 2.html, down here at the bottom, I'm going to create a link. It doesn't link to anything specific. It's a link. I'm going to give it a rel because I'm going to need to listen for (Typing) --- so that's my link that I'm going to create. Now this is clearly carousel related, so let's go into the carousel. Let's set up a click handler for links that look like that. I'll just simply say, I'm sorry, not carousel, details related. I meant details. This is the details module, so inside of init here we're going to listen for any click from the content that bubbles up to us from rel=js-select --- Did I call it select-person? Yep, select-person, from an element that has that rel attribute, and we want to do something with it. Guess what we want to do with it? (Student) Emit something. Well, if I've selected a person, the question is, do I want to load that person, so could I call loadPerson here? The problem with calling loadPerson here is that loadPerson expects an id, and that id hasn't been parsed out yet, okay? So let's have it call another function. I'm not using good creative names here, but I'll just call it selectPerson for now. Now his job is to --- I meant to put one other thing in the HTML. We need an id here to let us know what thing it is that we're clicking. I could put the id directly into the rel attribute, and then do a little parsing thing. I'm just going to do it even simpler by adding a data attribute like data-person=, and let's say we want it to load person 4. So EVT.target is the actual thing that got clicked, and it has an attribute on it called data-person, and the value there is the id that want to load. So that's ID. Did everybody follow me or am I going too quick? We're parsing out the ID from an attribute on a link that was clicked. So we could call loadPerson with that ID. Everybody following that? One last detail. We've got to put in those like preventDefault things. Don't want to forget that. But I'm going to make the argument that even this code, even though we're calling to our own internal function, I think this code is perhaps a little bit less than ideal. I'm going to make the argument that what we ought to do is EVT.emit. Did I call it select-person? I can't remember. Person-select, I'm sorry. I should probably spend more time not rushing through coming up with better names. Alright, so the event name was called person-selected, and it needed a piece of data. Now is that event going to end up calling loadPerson? Of course it is because we have that event handler set up, but I'm doing it indirectly. Now why would I do it indirectly? Well, what if there was another thing on the page that wanted to listen to this event? Like, for example, the carousel. What if we wanted the carousel to listen for an event like that, and scroll the carousel to the person that was picked, and highlight them. If we call loadPerson here that would not accomplish it, and we'd have to end up calling out or sending out some other event or calling out to carousel, but if we use the event system here we don't have to worry about that detail. We allow somebody else to observe that event if they care, or not observe the event if they don't care. What I'm getting at here is that I have intentionally created this layer of abstraction, and sometimes layers of abstraction are more confusing. This does take a little bit more brain power from you to think, oh, well the event's going to go here, and we're going to listen for it here. It's not as obvious the direct connections, but I'm arguing that there's a bigger point at stake. This is perhaps slightly less obvious code, but it's significantly better organized code because it's more flexible, it's more testable, it's less brittle. If, for some reason, the carousel module doesn't exist on your page there's no reason why the details module can't continue to act the way it should act. That's the point I'm making. Let me test myself to make sure I didn't mess something up. Oh, I think I need to --- Sometimes it's hard to get full refreshes here. Am I clicking the wrong guy? 2.html should be that Person #3. Sorry, just a moment. Trying to figure out how to get my browser to stop using its cache. (Student) Oh, you need to have --- refresh now, there you go. There we go. Alright, so I have this Select Another Person link, and when I click it we're expecting it to load up a different person, and in fact, it did. It loaded up person five. Now I didn't do the extra work of having it select the carousel or whatever. In fact, in the README you'll see I've left that as some extra credit. So if you want to go further with the exercise --- We've run out of time for me to do items one and two. They're pretty easy, and you can see how I did them in the solutions folder, but the major stuff is the stuff that we got to, which is this organization through events. Alright, so we're going to wrap up now, but I want to just leave one last space for any last questions. So let me check the chatroom. If anyone here has a question, speak up. The question was, can you explain again, why app.js must come first? App.js creates an object, window.EVT. I don't even need window.EVT here, now I can just do var EVT. It creates a global object called EVT. You'll notice that these modules need it right away. The very first thing they do when they run and define themselves as they need it, so we need to make sure app.js runs first before the header.js module defines itself, that's why. Observes the native version of an object that can send and receive events, res observers. That's way far field from the thing I'm going to be able to cover here Kevin, so let's --- it's probably not even my --- yeah, like you mentioned, it's probably better for Jafar to answer, but definitely way far outfield from what we want to cover here. Okay, any other questions? Now I know it's been an overwhelming day of a lot of heavy material dumped on. What I just ran you through over the last 7 or 8 hours together or whatever is what I would, if I were interviewing somebody, and somebody came to me as an interview candidate, and they said, I have 2 years' experience in JavaScript, then I would expect that person to easily handle the stuff that I threw at you today. So, essentially, what I'm getting at is I took some of you from having no JavaScript experience to an expectation level of around 1 to 2 years of experience, and that's nearly impossible to do in a single day, so if you feel overwhelmed, or if you feel like you missed some stuff, or if you feel like you need to go back over stuff it's because you do. It's because that's totally natural. We didn't stay at the 1 month experience level. We progressed quite rapidly, as many of you probably saw. The goal here is not that you come away from today already certified, I'm an expert, I've got 2 years' experience in 1 day. The goal is that you came away with the right sort of stuff to ask, the right sort of stuff to study, the right sort of ways to ask and think about stuff, and as you unpack this over the next weeks and months I want to encourage you strongly to go back to the exercises that we went through and try them fresh. Try them from scratch, and see if you can come up with the same solutions that we had in the solutions folder. That's really the best way to solidify the learning. Go back over your notes and the stuff that we did, and don't let this be the last time you see the material is the point I'm trying to make. Server-side JavaScript Middle-end Architecture We're going to try to switch gears a little bit and focus on applying JavaScript to some stuff. And this particular workshop is not exactly a formal workshop. This is more, we are going to basically just go through some code that I wrote for the purposes of being able to illustrate ideas that I have kind of espoused in various talks over the last several years. So just as a brief little history lesson that nobody would care about, but since you're listening to me, you have to listen to me anyway. Way back in like 2009, kind of towards actually the early parts of my speaking career, I was working at a PHP shop, and I wanted to be able to do JavaScript on the server because there were things that I wanted to do that were awkward, or harder to do with PHP, and I also hated the fact that I was essentially repeating code a lot. I don't know if anybody else has had this frustration of like repeating code before, but I was definitely having this frustration. My particular pain point was data validation rules, and I remembered back to my computer science schooling years before that one of the principles, one of maxims that I learned in my first programming 101 course is what we now call the DRY principle, but back then what they said in computer science school was any time there's more than one copy of something, one copy is always wrong, which nowadays we just refer to as DRY. We say don't repeat yourself. If it's possible to not repeat yourself, it's better to not repeat yourself. It's better to reuse something than to repeat it over and over again. Obviously those are not hard and fast principles, but they're guiding principles in software design. So, it struck me that I was repeating this data validation rule set in PHP, and I was turning around and writing the same code in JavaScript. And I had done that actually many time because I had written many, many different sorts of PHP applications, like years earlier than that, way back in 2002, I'd written like a timesheet application for a company, and I'd written all of the back-end stuff in PHP, and so I had all my classes and stuff like that in PHP, and then I had to turn around and write most of that stuff in JavaScript as well, so I was repeating some of that same logic over and over again. And any time I'd need to refactor something, I had to go back and refactor it in both places. And over the years, I worked in a lot of different shops; I saw a lot of different possible solutions to those sorts of problems. I worked in a Java shop, and I saw, I don't even remember the name of it, but there was some framework that probably Java people know right off the bat, but essentially, they expressed their data validation rules in Java, and it automatically generated JavaScript for them. It automatically wrote the JavaScript rules. They had no control over it; it just injected it into the page. That seemed like theoretically it was some solution to the problem because now the JavaScript gets pushed to the page, except we ran across a problem where there was one particular sort of check that was happening in Java that the equivalent in JavaScript ended up giving a different result. There was no way to exactly get the same check result in JavaScript that they were getting out of Java. It was close, but we ran across this one case. And it was annoying that I had no capability to go in and change the JavaScript because it was auto-generated on the fly, and I had to control over the code they were generating. So we had to work around that by writing a different set of validation rules and reformatting the way the data was coming in. It was sort of the tail-wagging-the-dog problem, like we wanted to fix the problem, but we couldn't, so we had to fix this other entirely different thing so that the problem would go away. So as you can tell, I've had lots of different exposures to this in different things. I've seen it in Python shops. I worked in a Python shop one time and a Django where thankfully I didn't have to do a lot of the Python work, but I did have to do a little bit of the Python and Django work, and in particular, the problem that I had was whatever framework they were using on top of Django, whatever their application framework was, it could not accept arrays of values from a JavaScript. Like if you posted an array of values, you couldn't post an array and have it automatically translate that into a Python array. It required you to have an individually named thing, which is great until you start doing UIs where they want to have a big set of radio buttons, for example, or checkboxes, or whatever. You don't want to have to uniquely name those things. That's annoying. You want to just pass an array of all the checkboxes that have been checked with true and false in them, but we couldn't do that. We just flat out couldn't do it. And the back end was sort of our restriction at this point because JavaScript clearly knew how to do it, but we'd passed the array in, and it wouldn't work. And so I'm just running into this problem over and over where code was being was repeated or things were being too difficult to do, bridging this gap between JavaScript and the server. And then there were times where I wanted to configure something about the server, I wanted to have some control over something about the server, like the way it was putting together the HTTP headers. I wanted to change that to optimize some performance, or I wanted to have more control over the way it packaged up files or whatever. And over and over again, from Python shops to .NET to Java shops and everything in between, Ruby and Grails and everything, I worked at all of them, and in every one of those jobs that I worked at, essentially, the back end ruled. And if you didn't know the back-end language, you just couldn't do what you wanted to do. And I was a JavaScript person, or wanting to be a JavaScript person rather exclusively, and this dirty secret was I had no control over the back end. So in 2009, I had started to get this conclusion like the problem is not that I haven't learned every single back end of every single job that I've ever worked at because that's not practical. It's not practical for me to be hired as a JavaScript developer, but have to become a Grails developer to do something. And that literally happened to me. I'm not making it up. I went into a job, very first day, hired as a pure front-end JavaScripter. I was hired to build an embeddable JavaScript widget. Totally JavaScript work, I wasn't hired to do anything back end at all, and I said to them on the very first day, the guy and that was kind of interning me, I said, alright, so what I need is I need an empty HTML file and an empty JavaScript file. I need to be able to serve those up, and that will be the basis for my widget, and so just tell me where to put those files, and then I'll go from there, and I'm good. Just tell me where and whatever your system is, where do I put these files. And I was imagining there was some special folder somewhere in this Grails application I could just drop a couple of files and bam it magically worked. And he said, oh yeah, you can't really do that. And he literally handed me this huge book on Grails, and he said, you're going to have to read chapters 4, 5, and 6 of this book, figure out how to set up a static routing for it, and do this, that, and he completely lost me, and I flipped. I was like are you kidding me? That's what I have to do to put an empty HTML, an empty JavaScript file out on the web? This is ridiculous. And so it was kind of this long boil that I had gotten to, and I kind of flipped out, and I was like I don't want to do all of that crap to put up some JavaScript files. I want control over at least the part of the server that I need to have control on. So in 2009, I started to formulate this alternate way of thinking about web architecture, and I eventually came to call it middle-end architecture. And to this day if you go to middlened.com, it redirects to a series of blog posts that I wrote about that concept where essentially I was suggesting there's a set of tasks that every application architecture needs to do, which I wanted to be able to do in JavaScript because many of those tasks, the majority of them in fact, are things that you need to do in both locations. For example, data validation, data formatting, routing, templating, caching, headers, those sorts of things. Those are all things that every application does, but they're also all things that you end up having to do a lot of on both sides of the fence, the parsing of those things and so forth. So I wanted to be able to implement that in JavaScript and reuse the code in both places, and my only option was to suggest some sort of architecture that would allow me to write the JavaScript and then use it in both places. And so I developed this idea of middle-end architecture. It's a tongue-in-cheek idea. What comes between the front end and the back end? Of course, the middle end. And I defined it as the top 10% of what's happening on the server and the bottom 10% of what was happening in the browser and everything in between, and I called that the middle end, and it involved all of those tasks that I was talking about. So at the time, there was no such thing as Node.js. We had a couple of things, like in the Java world we had Rhino, which still exists today, and it's being rewritten I think to a different engine or whatever, but we had Rhino, which was a way to do it, but that only worked if you happened to be in a Java shop. You wouldn't run a Rhino instance just of Java all by itself. So that didn't seem to work out for us, especially since I was, at the time I had moved on to a job where I was in PHP, and they definitely didn't want to have a Java tool in the stack. So what could I do? If I couldn't run something with Rhino or whatever, what could I do? And I had read that you could take the JavaScript engine out of the Chrome browser, the V8 JavaScript engine, that you could write some C++ bindings around it, and you could create a JavaScript environment somewhere. And I thought to myself, well I'll just do that. I'll just write a server-side JavaScript engine. If I've already go V8, all I've got to do is write some bindings. I've just got to make it accessible to the file system and a few other things like that, and that's all I'll need to do. So I set about to write a server-side JavaScript engine, and I in fact did it. I wrote an engine called Bikechain, and it's still up there on GitHub, not that anybody would ever use it, but it's still there if you ever wanted to go and look at it. I wrote this engine in JavaScript, and this was all before and contemporaneous with the launch of Node.js because if you fast forward to November of 2009, and I was at JSConf EU in Berlin, I was over there speaking, and sat and listened to a talk by a relative unknown in the JavaScript industry, Ryan Dahl, stood up and in his dry wit way announced this new thing that he had been creating called Node.js. And everybody flipped. I mean we all went nuts. It was standing ovation, and I mean it was crazy because everybody's so excited about this concept of getting to write JavaScript on a server. And I'm like yeah, that's what I've been working on for six months. We need this. It's an inevitability that we want to put JavaScript on a server. Within three months of Node.js coming out and as hugely popular as it took off I abandoned Bikechain because there was absolutely no reason to keep trying to do something a different way, but the process of putting JavaScript on a server, regardless of how it was actually done, the process is what I wanted. I wanted to be able to run JavaScript on a server. And to this day, that's how I feel about JavaScript. I don't actually care that much about Node. I'm not even all that emotionally wrapped up in this whole like forking from Node to io thing that's happened and whether they're going to come back together because for me Node is not a trademark. Node is not a command line. Node is a category. It's a category of applications that bring JavaScript out of the browser and put them in the place where I want them, which happens to be the server. It's a tool. And I don't think that Node and io are the end of this toolchain. They are the first modern step that we've had. By the way, they weren't the original. You know what the original server-side JavaScript was? 1997 LiveScript server from Netscape. Actually, '96 is when it was really kind of coming out. Brand new after JavaScript was out, we had LiveScript server. Netscape was the original, the OG of server-side JavaScript. Of course, it was pretty awful, and nobody used it, but nonetheless, the concept of putting JavaScript on a server is not new, but just in our modern age we kind of think of Node as like the big first step to modernizing server-side JavaScript, but it's not the last in my prediction. It's just the first big one that we've seen in a while, and we're going to see something that comes after it, and it might be a year, or two, or three years from now, but there will be some new idea that comes along. I'm anxious to see things like Firefox OS, which is JavaScript at the kernel operating system level. I'm anxious to see those things start to take over where we don't need a userland process like Node to run. We can just run natively JavaScript in any part of our application if we want. So I think we're going to continue to see that evolve, and I don't get so wrapped in exactly what is Node doing or not doing or whatever. Okay, question here. Oh, somebody just putting a quote in. So, that's a little brief history lesson that gives you a perspective on how I approach server-side JavaScript. It's a tool to help me solve problems. The problems that I like to solve are sharing code, not repeating myself, being able to do things in a buffered way. In other words, I want to be able to do my front end completely separated from how I do the back end, and that middle-end architecture I referred to, the back end essentially becomes irrelevant to the front end. So the front end never talks to the back end, it talks to the middle end, and the back end never talks to the front end. It has no clue what the front end is doing. Could be a mobile app, could be a website, could be another API server. It doesn't care. The back end simply becomes a headless black box state machine. It manages the session. It knows what state it's in. You give it some data. It gives you some data back. And that was attractive to me because I didn't want to have to relearn every single back-end system to figure out how to manage the headers, and the cookies, and the HTML files, and all that stuff. I just want you to give me some data. I'll figure out the presentation later. That's the Java, the middle end. So even though today I'm not going to espouse specifically this middle-end architecture, I just want you to have that as the backdrop for what I'm talking about when we go into this code. Secure Phrase Generator This code that I'm going to show you is a full-stack JavaScript application. That is, it's doing both the middle-end stuff and what we would consider back-end stuff all in one piece. In fact, there really isn't much of a back end because I'm not dealing with anything with databases or whatever. By the way, on the topic of data validation, the greatest part about data validation rules is you don't just write them once, you don't just write them twice, you actually write them three times. You write them once in your application code, once in your JavaScript, and then your database guy says oh, I don't trust them at all, I'm going to rewrite it in stored procedure. So now you have three copies of your data validation rules. But anyway, that's just a side topic. So what we're going to look at essentially is a way to, just in a very simple integrated way, write some code in a Node application in a Node/io whatever application that serves up the back end, if you will, the back end and the middle end of our application, and it tries in whatever ways possible to share some code with what's going to happen in the front end. So the app that I'm going to show you, let me just show you the finished version of it because it's actually a little mini site that I launched. Nobody's going to care that much about this site, but it's a little mini site that I launched called sercurephrase.io. I don't know if any of you have ever heard, hopefully, I haven't tried it today, so hopefully it's not dead. Have any of you ever heard of Diceware? It's an algorithm for generating secure passphrases using random word generation. Passphrases being not like your passwords, but the things that you would do--- yeah, this doesn't seem to be loading. I'll triage that in a moment on a break or something. Is it a connection issue? It probably is a connection issue. That's why you always have a local of something, right? It's like I've done this a few times. So, this is my little secure phrase generator thing. It's just a toy site, but I did it because I wanted something to generate these phrases for my own purposes, and I thought, hey, that's a great thing that I could teach with. So a week ago I said, I've got this workshop coming up. I want to teach some people some of these ideas. I'll just build a site. So this has been built in the last week. It's rough, it's not nice or great or whatever, but it does illustrate the concepts that we want to go through. And this is just, it's a silly application, but you tell it how many words you want in your phrase, it generates the phrase, and it gives you some nonsense phrases to use as your passphrase. So there's a couple of things to observe about this application. Actually, give me just a second. It appears to be--- Yay for demos. Actually, it's kind of fortuitous that it's working. You'll notice that it's working, but if you look closely, every time I click that, it's actually doing a full form submit. Something about my client-side JavaScript isn't working correctly, and I'm going to have to check into what's going on with that, which I'll look at over a break. But basically what this is doing is it's illustrating the idea that I want the server side to be able to do this work exactly the same as I want the client side to be able to do the work. I don't want to have to rewrite this logic for generating passphrases in both places. So in the fallback case, which is what's happening here where my JavaScript is somehow broken for some reason, in that fallback case, I want it to be able to just gracefully fall back to calling back to the server and running the exact same code on the server. And I wasn't intending to show you that, but it's broken in some way where JavaScript's not getting served up correctly, and it still falls back to sending that request across the wire and working the way that we'd expect. server.js Walkthrough We're not going to start this complex. We're going to start with something a bit less complex. So what I'm going to do is stop that server. I'm using a tool called forever to run my node processes in the back end, and I'm going to recommend if you don't already have the installed, if you have your Node environment up and going, if you do npm install -g so that you can install it globally and then do forever, that's a nice, simple tool that will start up a Node process and then monitor it, and if it crashes, it restarts it. And crashes are pretty common in server-side JavaScript programming, so it's kind of useful to run stuff with forever. So npm install -g forever, and then you should have a tool on your command line that you can run forever like I was doing. But anyway, what I'm going to do is switch to the base version of this code, node, I'm sorry, ./server. If you're running on a Windows machine by the way, you're not going to be able to use the Bash script that I've provided, that server.sh, but if you look at server.sh, it's not really doing something entirely crazy. It's basically killing the previous one, so you can do that yourself. You can say forever stop and kill the previous one, and then it's starting it up again. So you can run that command, the forever start. You don't need these other things like the Uptimes and spinSleepTime. So just forever and then start, and then give it a code, and it'll run and manage it for you, or you can just run the command line, like run it through Node. We'll get to that in just a minute. So for me, I'm just going to run server.sh to start up the base version of this code, and I'll go back to port 8050. So you see a really baseline version where I don't have any of this stuff going on about interactions or stuff. But this is kind of our starting point. So what I'm going to do is spend a little bit of time talking to you about how this code currently works, this base version. I'm going to walk you through different files and point out some things that I did. And then, time permitting, we'll try to put in a few little extra things to make it look more and more like what I was doing with the secure phrase site. And you'll have both of those code bases from here on that you can kind go and refer to. The first thing that you're going to notice right away if you've already looked at any of the source code or once you look at the source code, you're going to note that I'm not really using, I'm not a framework person, and I'm not using any kind of like special framework or whatever. This is barebones JavaScript stuff. There's a few little libraries that I pull in to help with stuff, like forever is a nice little helpful tool, but this isn't like I'm writing some Angular app and I've bought into some big ecosystem. These are principles that I think are at a lower level of the stack than what framework you choose. And what bugs me frankly a little bit about framework choices that people make is that it restricts you from making some of these decisions yourself. It kind of forces you down a particular path. I don't like to be forced down those paths. I like to have total freedom. So this is sort of our frameworkless way to do shared code. There's a term that's often used, or thrown around; it's called isomorphic JavaScript. Let me just address that term for moment. It's a completely BS term because if you know the mathematical principle of isomorphism, if you know what isomorphic is supposed to imply, this idea that, it's that it's a value that is in a different form, but that can go in either direction. So if I take a value in one form and I convert it to another form, and then I can come back and I get the exact same value, that's called an isomorphism. And the principle of isomorphism means that I need actually something in a different form, but that's not actually what we're doing here. We're not actually taking JavaScript and making the JavaScript in a different form. We're making the exact same JavaScript and sharing it. So a better term for this principle of reusing JavaScript is to call it reusable JavaScript, or shared JavaScript, or hybrid JavaScript, but this isomorphic term makes you sound smart, but it's not actually accurate. There is a way to do something that's kind of like isomorphic JavaScript, but that's not what anybody's doing. That would be if you wrote your back end in something like Java or whatever, and it automatically produced some JavaScript to replicate itself in the browser, and then there was a one-to-one relationship where that JavaScript could produce the same Java from itself. That would be isomorphic JavaScript. But nobody's doing that. So let's not use improper terms just because they're buzz wording. So I'm going to call it shared JavaScript or hybrid JavaScript from here on. And we'll take a look at some of the code. So I'm going to start by--- shared-js--- I'm going to start by opening up the sceret.js file because this is where I set up some configuration constants. So I just want you to be aware of what configuration constants I'm setting up. I'm setting up that the server address, we're listening only on localhost. So sometimes people, sometimes your machine won't work if you actually say localhost here, even though it ought to. I've seen weirdness with Node in the past, so I always specify the 127 address. And then I picked port 8050. I don't know why, it's just one of my favorite numbers for demonstrating stuff, so port 8050 is the port I chose. Some of these other ones really aren't even actually being used, but they're there in case you would use them in the future, like some of the headers that you send out if you want to make cross-origin XHR requests and things like that. This is if we're doing static file caching, we can set up some links. So mostly we're basically just using the server name, server address, and server port. Now, let's open up server.js. It's kind of the main meat. That's where our main portion of our server works. And right off the bat, you'll see that I'm starting out in strict mode. That's a really important thing. It's easy to forget. I think you ought to be running in strict mode. Put that at the top of all your files. Just get into the habit of making sure that your code is running in strict mode. I'm going to uncomment this. I have it commented out because we don't necessarily need it running all the time. This is actually kind of a useful like debugging trick if you haven't heard about this in Node. In Node, if an uncaught exception chokes the server, it will actually kill the server and throw it into this weird state. But there are times when you actually want some sort of interactive debugging going on. There's a way to debug Node processes. We won't get into a lot of that. But there's times when you don't actually want it to just kill the Node process, and it's especially true if you've got some bug and you're running something like forever, which is going to keep restarting it and keep hitting the same bug. So turning this on, turning this uncaughtException handler on, allows you catch it in a graceful way. You're not going to necessarily want to keep the server running once that happens, but it does prevent the system from entirely going away and restarting. So I've found that to be a useful little trick to listen for the uncaughtException handler. Okay, so at the top I start setting up my variables. This a style that I've recently fallen into, which is that I put all my variables at the top and my functions at the bottom. I only do that in Node. My browser's code I actually end up doing the reverse, and I can't really fully articulate why, but it's just a style I've fallen into recently. I find it easier to have all my module declarations, my require statements, at the very top so I can see at a glance everything that's being pulled in. And I think that's going to likely be more how we structure our modules in the future anyway. We're going to be doing a lot of import statements that are probably going be at the top. So this kind of more closely mirrors that. And you can see I'm importing several base Node modules, like the file system module, the http server module. The node_static module is how I serve up static files like the CSS and JavaScript. Path module for parsing file system paths. Url_parser, this one parses URL strings. This watch one I'll explain later, but that's how you watch a file system and do stuff if things change. Now I start setting up some variables, which I'm doing anything with yet, but these are some variables. These are basically the representations of the modules that I plan to use in both places. So ASQ, that's going to be my asynquence library. Grips is my templating engine. EventEmitter2 is an event library that let's you have very lightweight pub/sub kind of thing. Events is going to be my actual module that uses that, or my actual instance of EventEmitter2. Tmpls is going to be templates manager, so it interacts, that's actually the compiled templates from grips. Pages is going to kind of be a page controller, so it's going to handle mostly in the browser, a little bit on the server, but mostly in the browser it's going to handle things like managing my history objects so that my URLs, in a single-page app, my URLs are probably mapping with my back button and stuff like that. So I'm going to use the history API in that one. The View module is directly interacting with my templates. And the Request module is abstracting away if I want to request something. When I'm in the server context, a request is just a file system load, but if I'm in the browser, it's an AJAX. So I just create a little wrapper on top of that so I don't have to think, and I can use the same request in both places. And then finally, a variable called routes, which is going to be an array of basically, if you've done any work with Express or if you've done maybe something like Koa, that's another generators-based routing server that's similar to Express, and there's even modules that let you use them together. But essentially, I'm going to recreate that without a framework, and I'm going to do it in just a few lines of code, and my routes array is a series of functions that will perform my middleware paths. So here I start pulling in some stuff. This is requiring in that secret file, setting up some static file options. These aren't used yet in ours, but they're used a little bit, but not a lot right now. You notice that I have it set up so that you can switch this from DEV to PROD, which changes file caching modes and things like that. Alright, so here's where I start loading in those modules that I was talking about earlier. And I'm doing something interesting that is definitely typically considered an evil thing to do in Node. Most people say you should stay away from the global object entirely. I can't fully endorse this technique without any side effects, but I would say that it has become increasingly useful in the process of sharing code if I treat my hybrid module, their namespaces, as being on the global object. The difference is if I wanted to do this in a fully-modularized way, I'd have a very different mechanism running in the browser, something like require, that would be managing my module instances in the browser, and it would look very different with how I would interact with those modules in the Node server. And I don't want things to look significantly differently, or it kind of defeats the purpose of trying to share code. Even if the code itself was shared, if the way that I use it is very different, I don't really want to go about that. I'm also not a big fan of--- Could you refactor? Sure you could refactor server.js. This was a quick and dirty site that I built in three or four days for the purposes of showing off some stuff. This is certainly not production-quality perfect code. So what I'm doing is I'm basically setting a local variable instance in my program, but I'm also making a reference to that same thing on the global namespace. And what that means in my code is that inside of those modules, if one module is using another one, I don't need to worry about different sorts of imports on the server as I do in the browser. The other way of going about this by the way, if you don't want to go this route with setting the globals, is you write server-side modules, and then you use some tool like Browserify, which completely rewrites your code and makes it look like something that'll run in the browser. And I've done that before, and I'm not saying Browserify's bad, actually it's a great tool, but it's a lot more mental juggling to think about the code that's running in the browser has been transformed now, it's rewritten your code, and I would rather literally use the same code while I'm learning things and so forth. So for me, Browserify was heavier than I wanted to go with this project, but it is another way of handling what I'm doing here. So I'm loading in some of these libraries like asynquence. This is the contrib packages on top. Here's the grips templating engine, my EventEmitter. These are me loading in those pages and views and requests. Alright, so I have a function, which I'll show you a little bit down below called loadTemplates. It's supposed to go and take this Tmpls.js file, which I'll show you where that comes from, but it's to take that file, run it in my current context of my engine so that my server-side process can render templates if necessary. And the principle here is what I call sort of hybrid rendering, which is that on the initial page request or any page request that actually goes to the server, the rendering engine should be invoked and should render a full HTML page ready to ship out to the server with all of its data. But once we then ship out an application and we are in the page in the server, I mean in the client in the browser, now you want for your JavaScript to take over and to do single-page app things like being able to re-render a page using the exact same templates with the exact same templating engine. So what I'm doing here is I'm loading up the templates into the server instance so that it can make those initial requests, but we do the exact same thing. We load those things up into the browser as well, and it's literally identical code. It's the same templating engine, it's the same templates that have been compiled, everything is exactly the same, and it runs the same in both places. So it's really a significant amount of sharing that's going on. And what I need to do is basically load up this file. So let's take a divergence and ask--- So there's a question. What is the purpose of asynquence? Asynquence is a flow control library, so it manages things like promises and generators. Anything that you're doing asynchronously, instead of using native promises or whatever, this is a library that kind of helps glue all of that stuff together in a better way. And so I'm going to be using asynquence down below to do, and across the modules in quite a few places, so that's what it's for. We're going to use it in quite a few places. Building Templates So where does Tmpls.js come from? You'll notice it's in the web/js directory. Where does that thing come from? Well I actually have another utility here called build-templates. It's a script that is in the main root of your file. And if you look at build-templates, let me zoom out, it's just a little easier to see more at a time, what build-templates does, I can scroll down here, essentially what it does is you spin it up, you run this program, and it will process through all the templates that are in the templates directory. These are grips templates. If you were using a different templating engine, if you didn't like grips, then you'd just be using a gulp or a Grunt process for whatever engine you want. Again, not to overload people, we're not using Grunt and gulp here. I'm not saying that those aren't good tools, but that's yet more machinery that I have to teach you. So I'm showing you how to do it without even invoking any other tool. This is just a simple script that I wrote to go through the files and templates directory and run them through the grips templating engine and compile them. So that's what it does. It loops through all the templates in that file, processes each one of them. This is a command in the grips templating engine to compile one of those files, and it compiles it from the HTML template into runnable JavaScript that can then be rendered either in Node or in the server. So essentially, this build-templates JavaScript file produces the Tmpls.js file. It starts with--- Is it similar to the EJS template engine? Similar in that they are both template engines, yes. Similar in style or syntax? Definitely not. Okay, so there is a base wrapper that I have, and right off the bat this is going to illustrate how I share code between Node and the browser. I use the UMD style of module wrapper. Now I will fully admit and agree to you that those five lines of code, being boilerplate in the top of each of my files, is not at all ideal. I don't like that crap up there. But the other takeaway is that I don't even have to worry about it. I can literally just hide it, which is what I often do. I don't have these hidden because I want to teach. But I can just hide those things and not worry about those sorts of details, which is usually what I do when I'm really trying to think about it. So I can use like code folding and Sublime, and then I don't have to worry about that UMD header. But this is essentially replacing my need for Browserify because this file, as it is, can be run in any of those environments. It can run in Node, it can run in the browser, it can run inside of require in the browser, and it doesn't need to be transformed. So my choice instead of using Browserify is to use the UMD wrapper. Some people like that, some people don't. I'm not passing judgment that Browserify is bad. I actually think it's a great tool, but my choice here was I don't want to invoke some other tool that I have to teach you. So another way of doing it plain barebones is to put in the UMD wrapper. And I don't write this every time. I just duplicate my file. I duplicate another module, and I don't even think about the boilerplate stuff. The contents of my module is what starts here, and you'll notice that my module is in strict mode. And I have this init function, and I have a little placeholder here, a comments placeholder. That's where the compiled templates get put into. So this is a wrapper, and I compile all the templates with grips, and I stuff all of that executable code right in here. And that is the Tmpls.js file that can work identically in both the browser and the server. Okay, the other thing that build-templates does, in addition to building the initial template bundle, is it sets up a watch, and this watch is duplicating the same sort of feature that you've probably used in something like Grunt or gulp. I'm setting up a watch to listen for templates being changed in my templates directory. Every time I save a file, this watch will automatically kick in. It'll see that that file had been created or changed. It'll kick in and reinvoke my build-templates script. So it'll rebuild my template bundle every time I make a change. I don't have to go back to the command line and do it. It just automatically watches it. So essentially when I start this up, I just, I start up build-templates, and then I don't think about it anymore, and it automatically builds. Now another thing on that topic is I said I had watch going on in my Node server process, so I'm back in server.js, and I said I had Node going on in my server watch process. Where is that going on? Well here I have another watch.createMonitor, and I'm watching for the Tmpls.js file to change. This is an interesting trick I haven't really seen a lot of other frameworks doing. I'm not saying that nobody else is doing it, but essentially what I want is to not have to restart my server if my templates have changed. So I'm hot reloading my templates bundle into my server instance every time it changes. In other words, when I change a template file, one watch process rebuilds the template bundle and another watch process re-hot loads it directly into my server instance without restarting. So I can just do a refresh of my page immediately after changing my template, and bam, the new view is available. So let me illustrate that process just to kind of point that out, and that will segue us into talking about these grips templates. So I just have a basic one, this index. Here's my content, my basic content. So if I wanted to make a change, I don't have that build-template process running yet, so before I even save the file, let me start up that build-templates watch that's going to go on. So now that's in the background. The build-templates watcher is in the background. Actually, let me run it. You have to run it with the watch to make it do that. So now it's watching for that change to the template. So when I save this file, we can come back to the command line, and you'll see that it has now rebuilt my template bundle. My server was automatically redoing, or watching for those things. So if I look at my server log file, (Typing) you'll notice that it reloaded my templates. So my server has reloaded the templates into its process, which means without even restarting the server, if I come back over here, now it's updated, and it can serve it up from an initial page, and we can also hot load that JavaScript into the browser if we want. I don't have that process set up, but it's easy to do the same thing in your browser and hot load your new templates. A couple of quick things about grips, just if you were at all interested in learning how grips works. I have a little online playground for the template engine. So these four boxes, this is the template that you write, and then this shows you what it gets compiled into, and by default that's the code that's compiled with all of the debug stuff in it so that it gives you nice, friendly error messages, and that's what you'd use in DEV, but if you wanted to switch it to being smaller and being production without debug stuff, switching the mode, this shows you how much shorter the code is when I don't have all the debug stuff in. So you can kind of get a sense, and if you wanted to look at the code that I was producing, it's pretty highly compressed stuff, but if you at all cared about it, most of that stuff in there is things like this, which are producing information that an error message can use. That's a distinction point between grips and other templating engines is that there's actually quite a few features in there that are built for much better error messaging than you've seen with other template engines. It's much, much richer, stack-trace-based sorts of error messaging from your templates, not only from if you have an error compiling your template, but much more so if you have a runtime error with your template. There aren't a lot of template engines that do runtime error checking in any graceful way, but that's been built into grips from the beginning. Alright, so you can change something about your template, you can change something about the data that's being put in. So if I change this to World2 and I come out, I've unfocused from that, it doesn't need to recompile, but it will re-render and shows you now that it says World2. If I change my template up here, I'd like to add in an extra couple of exclamation marks, it will actually recompile the template first, and then it will re-render it and show you the info down there. So just a little playground if you wanted at all to learn about the syntax. There's a bunch of documentation and then a bunch of different preset examples that show you doing different things with the template engine and how it produces stuff. So if you want to learn grips, that might help a little bit. But we're not really doing a lot of complicated stuff with grips here. All I'm doing is I'm defining. The define tag is how you define a partial. To include a partial from another location, you just say partial and give it the ID of the partial. So I have this stuff template down here, and, of course, all I need to do then is add more stuff into any part of my template, click Save, let those watches run for a moment, and now if I do a refresh, we see the exclamations show up. Grips is definitely a partials-based templating engine, so you define things in terms of template partials. Also, you'll notice that files can extend other files. So I have a master template that I've set up for the page, which has like my DOCTYPE stuff in it, and then I'm calling out to a partial content, which allows me to do essentially a basic, but powerful form of template inheritance. So the index template inherits the master, and it overwrites certain partials. So I can have lots of different pages that inherit from master. I could have something that it inherited from index and overrides partials. So it supports those sorts of features. I was going to see if I had any examples of--- Yeah, so here's how you drop in a value instead of dropping in a partial. You just can insert it. By the way, grips does have a shorthand form of all of the syntax. So the long form is, like it uses words like define, but there's a shorthand form of all the syntax if you prefer to right less code, and the short form uses a single operator in place of these different words. So if you have a really long complex template and you find yourself writing a bunch of words, you might like the short form it can use. Either form is valid. Main takeaway here is it really would not matter at all what template engine you like to use. I don't care if you want to use Mustache, or you want to use Dust, or whatever, whatever template engine suits you. The same concept that I'm presenting here can be done very easily with any of those templating engines. You just simply have a template that you change a file, you have a watch that rebuilds it, and you load that into some file that you can use in both places, and then in my server, if I want to use the template engine, it's exactly the same as if I'm using it in the browser. So let's look at this loadPage route. You'll notice that I'm calling out to my View, sort of like a controller, if you will. I'm calling out to my View, and I'm calling this function called getPageHTML. That just simple invokes grips, and it loads the appropriate section of HTML, and then it sends it back out. So this View.getPageHTML wouldn't have to change at all if you wanted to swap out a different templating engine. You just go into that getPageHTML and specify a different template engine. Templating Questions Quick question? Yeah. Is there a way that I can tell the watch to ignore certain file names? Oh yeah. If you look at the documentation for the watch module, there's all kinds of special configurations and filters and stuff. Good old Emacs creates special files. Yep. I don't see any other questions. A couple people just mentioning that they do or don't like certain things about the templates. Alright, so the next thing that we want to talk about, that's how I'm reusing my template engine. So I'm doing my rendering exactly the same in both places. And actually, let me just prove that to you. So here I show you how I'm doing it on the server. I'm calling that View.getPageHTML. If I open up web, js, Pages.js, I'm sorry, View.js, no let's look at Pages. Pages is my page controller. If I look at that, this is the thing that's running in the browser, and whenever something is asked for, like if we tried to load up a--- So this one is my click handler for lengths that I basically want to AJAXify. I'm listening for any lengths that aren't marked as being ignorable. And if I recognize the href of that tag as being an internal page that I have a template for, then I simply call this gotoPage function, which, not terribly surprisingly, is going to call View.getPageContentHTML. So it's the exact same path, and this code ends up running exactly identically between server and browser. Okay, let's see here. Would you say React would be good here? React is awesome, but I think it's a much bigger hammer than most people need. That's what I'll say. Oh, by that way, on that topic of like what are other potential options or whatever, I don't know how many of you here in person, or online, or listening to the video have heard of Ember, but it's kind of a, it's one of the big three, if you will. So there's Ember, there's Angular, there's React. It's kind of one of the big three at the moment in that whole like framework, rendering sort of thing. Now I'm not using Ember. I'm not an Ember user. I know quite a few people who are. They're really smart people. So I am not in any way, shape, or form suggesting that Ember is bad because I don't use it. It's way overkill for what I need, and that's why I don't use it. I always start with the simple stuff first rather than pull in a huge framework that is mostly what I don't need. But there's one particular point I want to bring up about Ember. And this is a praise of them. It's not a criticism at all. Just recently, Ember released a whole series of new stuff, and if you have kept up at all or read anything about it, they released a new thing called Glimmer, which is a new way of doing their rendering and stuff like that where they're looking at their template partials, they call them different things, but they're essentially template partials, and figuring out the minimum template partial that needs to be re-rendered and then redoing it. That's really, really cool stuff. And that's exactly why I built grips five years ago because I was doing that exact same thing. So I'm really excited to see a really smart set of people come along with a much bigger platform than me, and they're starting to do the same stuff. And then they have their other, their server-side engine, the Ember CLI tool, and they have, the name is escaping me, but they have now a process where you can run their rendering on the server in Node just the same as you can run the Ember app in the browser. And if you dig into the details of how that particular tool works, that's exactly the same ideas that I'm espousing here, reusing the code in both places, doing initial page load render in the server, and then letting the app take over and progressively enhance to a single-page app. That's exactly the same stuff I've been talking about here. It's entirely compatible with the ideas that I've had with middle end for years. So I'm super excited. Even though Ember is maybe more overkill than I need, I'm super excited that a really smart group of people has come to similar conclusions, and they're now pushing that forward. We're going to see a lot more people get on that bandwagon I think because there's a lot of value to this simple idea of being able to share code and have it work. Yeah, FastBoot, that's exactly what I was talking about. People doing the same things with React right now on rendering the templates on both sides. And then the same with Angular, and I know Angular2 right now, like if you look at the reading notes, they're really discussing this concept in detail. So the good news is over the next couple of years basically everybody's going to be doing it. And you can do it the simple way with no frameworks and just a little bit of code yourself, or you can use a framework, and the frameworks are going to be doing it. But the value is in the idea, not the implementation. Routing Functions The next thing I want to talk about in terms of how this code's working is not so much about the reusability, but how can I express things in a simple way without needing some kind of framework. Essentially, I have that routes array that I was talking about, so I'm pushing functions into my routes array almost identically to how you push middleware functions into an Express app. If any of you've done Express work, then you do app.use or app.get. This is the exact same concept, but I'm just using an array rather than a framework. So basically, I've replaced the Express framework with an array, and my API is the array.push rather than app.use. The concept is the same that I have a function that's going to receive a request and response stream, and it's going to decide if it should do something with it or not. So I have this series of routes that I define one at a time. This first one sends out the server header for all inbound requests. This one sends out a set of security headers, so my Content-Security-Policy and my Strict-Transport-Security. If you don't know what those are, you should definitely do some reading up on them because they're really important for modern production apps. And then I have this route, and this route is waiting until the entire request has come in, if it's more than one chunk, and it's putting all of that into the body. So I'm essentially setting up that data listener, though you've probably been familiar in Node. I'm setting up a data listener and listing for it and then moving on once it's complete. And then--- let's see if there are questions here. No, I'm just chatting with someone. Oh, okay. Then I have a route set up to handle my favicon. I don't know about you, but I am constantly annoyed when I do server-side programming. I'm constantly annoyed by the fact that my Chrome browser, for example, is always asking for a favicon, and most of my apps don't have one. So I just set myself up a little route that listens to the favicon request and just does a cacheable 204 response to try to get the browser to stop asking for a favicon over and over again. So that's just a simple little route. There's nothing non-Node here, or magical, or special. This is a route that I set up to recognize a request for one of the static resources, like a JavaScript file, CSS file, images, the robots text, whatever. Those static file requests, if being handled, I use this static_files.serve, which is almost identical to the static file server that comes with Express, but I just have it in standalone form. And then I have another route, and this is the one for, if none of the other ones have taken over, this is the one that says they're asking for a full load, or we're going to check to see if they're asking for a full loadPage. So the first thing I do is to see if the request was a GET and if it's one of the pages that I recognize as my internal templates that I can handle. So if it's a request that I know how to handle and render, then I go ahead and call View.getPageHTML. I render out the response. And finally, my routes array has a default route that if none of the other ones match or handle anything, it just gives a 404 response. So how do I make these functions in this routes array actually process through and run every time a request comes in? Well, there's lots of different ways to do that. Express does an internal for loop every time it comes across, but I basically replaced all of Express and maybe all of Koa with this one function that I wrote called router. Let me zoom out just so you can see how big it is because it's not actually that big. So it's this one function here called router, and it's a special kind of function called a generator. So that little star, let me zoom back in so you can see, that little star means this is a special kind of ES6 feature called a generator. And the other reason I'm using a generator here is because it has a really nice syntax for me to be able to pause local stack inside of the function using the yield keyword. So this is basically saying if I have a route, basically I'm going to loop through my list of routes and call that function, and if that function returns me, in this case this is kind of like a promise, but it's asynquence's version of a promise, if it returns me something that I need to wait on, then I'm just going to simply call the yield and wait for that thing to finish. So that's the way I do an asynchronous route as opposed to I'm ready to finish the route right away. That's a way to pause the generator by simply yielding out a promise. And then if any one of those routing functions returns true, then I break out because I know there's no more routes that need to be consulted. If any error happens, the try catch works. The cool part about generator is the try catch works even across asynchronous calls because it has synchronous semantics inside of it. So it's a really nice way to simply express error handling with a try catch. And finally, the last thing I do is I see if there was an error, I throw back an error that has a little bit of extra data in it. It has the reason, but it also has the request and the response stream. So, this generator doesn't run all by itself. It needs something to run it to be able to handle the yielding of promises and whatever. And if you've ever ready anything about generators, I've got a book about it, I've got blog posts about it, you can read lots more about generators, but there's lots of frameworks out there that are able to take a generator and automatically run them to completion. Asynquence also has one. So because I'm using the library, why not just keep using the same tool? And so essentially, we go to the magic, if you will, of how all of this HTTP routing is happening. Getting a little dizzy here. Sorry. I was getting lost in my own mind. So this is the magic, these few lines of code. This is the magic that actually makes my handling of incoming requests work. Let me skip over the react part for a moment because that might be confusing. Let me just look here and say every time an incoming request happens I'm going to spin up the generator and run it until it's found a usable route, and if any usable route happens, then that's just the end of it. If there's any error that happens, it actually bubbles out, and I have a responseError function. So if we look at the responseError function, looks more complicated than it really is. It's basically just saying if you've made an AJAX request, I'm going to respond with JSON; otherwise, I'm just going to log the error to my server log. So if any error happens anywhere in any of the machinery, no matter how deep, if everything's using asynquence the way I've set it up, that error will bubble all the way out and get handled in one event handler so I don't have to leak that logic all over. Streams Now what about this react thing? So the observation that we need to make is that promises are really powerful, but they do not map well to event streams because a promise, once created, can only be resolved once, which would be great if you were only ever going to get one request against your server, but you're not. You're going to get lots of them. And so there is this principle of streams, which are what the request and response objects are themselves, but how do we asynchronously respond every time a new stream spins up? How do we handle it? Well one way of doing that, if I were to just suggest some pseudocode, one way of doing that is you could have a stream object that represented this stream of incoming requests, and you could listen for, you know, whatever the event might be. I think it's the request event that the HTTP server spins. And inside of here, that is every time a new request comes in, you could fire off your whole stream of routing across this thing inside of this function. And many people do that, and it's perfectly fine. But one of the downsides to it is that now you just have a regular function, and all of the stuff has to be self-contained inside of that function, and it's a little bit awkward to call out to other modules in your application and so forth. So redefining if I were to just sort of pseudocode it, if I had some big stream of promise chain going on here, I'd have to be repeating that promise chain over and over and over again every time this event fired because I'd make one promise chain for each request. So what essentially, if we were to boil down, if you've heard about reactive programming, if you've heard about the Microsoft RxJS library, super fantastic, but also crazy complex. I mean, the stuff that they support is unbelievable. If you've heard about reactive programming and about that whole model, essentially, when you boil it all down, what they have is this notion of inverting this paradigm to create something that they call an observable, and an observable is something that is going to get notified every time an event happens, and it'll send out a new stream of asynchronous stuff every time that event happens. So it's a way to adapt your asynchronous flow control to an event stream. And they have a whole bunch of different ways in the RxJS library of doing that. By the way, my usage of react and my usage of the word reactive programming is not at all the same thing as the Facebook React framework. It's a very unfortunate overlap of terminology, but this doesn't have anything at all to do with Facebook's React. They're a virtual DOM rendering thing that mostly runs in the browser. That's not what we're talking about here. We're talking about reactive programming, reactive programming being essentially adapting a stream to an asynchronous flow. And so in my library, I have a method called react, which allows you off the end of the react to define an arbitrary chain of your behavior once, and every time you call the trigger it will fire off a new instance of the chain for you. So it's uninverted. Instead of defining the chain inside of the handler, we define the handler and then the chain. And that really is actually the most 50,000-foot basic view of what reactive programming is about is inverting that paradigm to adapt streams to asynchronous flow control. So it's really nice and easy here. All I have to do is listen for the request event, and instead of having a function that has to declare all of my stuff, I just trigger it all, and that's what runs my router through this runner function. Now, I understand if you haven't done a lot of asynchronous programming with promises and generators, some of that that I just glossed over might feel a little bit like wait a minute, I haven't dealt with promises and generators before. That's fine. There's a lot of work to do to relearn all of these things. I've been doing it for a while, so it's easy for me to just rattle off. I understand it may be new to a lot of you. There's lots of resources out there about this topic. I have a book on it. There's a couple of dozen different blog posts that are out there about it. There's a great talk by a guy named Jafar who's got a training with Frontend Masters on asynchronous stuff. He's really even pushing the envelope further than even I'm talking about. I mean, he's going crazy with new stuff that he's proposing for ES7. So there's dozens of different ways that you can start to learn more about asynchronous programming. The point of today's talk is not really to get too bogged down in the weeds with asynchronous programming, but I just wanted to point out that those few lines, plus this 40-line function, is essentially a full and complete replacement of the Express framework or the Koa framework. So I'm just trying to illustrate that you can do these concepts without necessarily having to learn a whole new framework. Do you mind a question? The asterisk on that router thing, you said that makes it a generator? That's what makes it a generator. Is that only a convention or is it--- No, that's a real thing, like it's a syntactic requirement. There's a question that popped up. How can we export variables and functions to other JavaScript? Not sure if I understand the question here. How can we export--- Perhaps that question in chat can be clarified because I'm not really sure what the question is asking for. There are about 15 seconds. Just move on. We'll get the question. I'm not saying frameworks are bad. I'm simply saying that frameworks make a lot of extra stuff for you to learn, and if you're looking for a way to get in and start playing with stuff without having to learn 15 other framework's APIs, this is just basic JavaScript, and I'm showing you that the concepts are much easier than the frameworks themselves can be. First thing I want to illustrate is working with those templates. So in your shared-js folder, we can open up the index.grips.html folder, I mean the file, and then I'm going to actually duplicate it. I'm going to save it off to another name in that same folder, and I'm going to call it about.grips.html. So now I have two different files that both have the same content in them. But let's take what's in about.grips, and let's change it so that it's clear that that's the about page. So maybe change the content of your h1. (Typing) Okay, now I have created a file and saved it, and I have not touched my server in any way, shape, or form. And I'm not even going to change the master template to add it to the nav, but I can in the next step. All I want to do is illustrate that having done nothing but add a file and save it, hopefully this doesn't blow up on me like other live demos have today, I should just be able to add /about onto the end of the URL. Actually, I'm going to have to refresh so I get the new JavaScript. So refresh, and then add /about onto the end of the URL, and it should load the about page that we created. So that was a load from the server because the server was aware of it. So now let's update our nav. Go into the master.grips template, and you'll notice that I have a nav element here with a link. So I'm just going to add another one. That's it. Just added another one. Having saved that file now, everything has completely rebuilt itself in the background. So when I refresh my page, I now have a nav that I can click on and switch between my two pages. So I didn't have to make any changes to any of my routing or any of my code or whatever because that code is all dynamically adapting itself to whatever templates are existing. As long as there's a template for that URL and it can recognize the template based upon the URL, it automatically invokes and renders that template. So now, as I'm switching back and forth, these are not actually loading from the server anymore. These are re-rendering that partial in the page and swapping it in just like any normal single-page app. Whenever I do a refresh, that's when it actually makes an initial request to the server, and the server renders it, and then immediately the JavaScript takes back over, and now we're running in single-page app mode. Adding a Shared Module Creating a Random Number Module But let's decide that we want to make ourselves, just because I'm not creative enough to come up with something that we have time for that's like the secure phrase generation, so I'm just literally going to create a random number module, which does nothing but call math.random. But we're going to illustrate again this point of creating some code and using it in both places. So what we want to do is first come up here to our place where I've got my hybrid server browser modules, and you notice I have one here that was kind of already a placeholder anticipation. So I'm just going to uncomment that. We're going to call our random number thing Foo for now. So uncomment that variable, and then come down here. I've got it commented out. You can uncomment that line, which is going to expect to find, as you see on line 67 there, it's going to expect to find a Foo.js file in the web.js directory. It's the place where I'm putting my hybrid shared modules. That file doesn't exist, but we're going to create it next. So I don't want to retype all that boilerplate code, so what I'm going to do is open up one of those ones that already exists in that location. So come to the js directory. Let's see, what's a good one to use? Let's use View.js. Just open up View.js, and let's take out the stuff in the inner contents of View.js. And don't save over View because you need it. Save As, and duplicate it, and call it Foo.js. One little minor change you'll want to make sure you do is change that word View there on line 5, change it to the word Foo so we get the proper naming for our module. Okay, so from a perspective of defining ourselves a module, we want to have some internal characteristics inside of our module, and then we want to have a public API that we can interact with in some way with our module. So my internal characteristics are let's suggest that I have a function that I call random, and its job is to return me a Math.random number. I know that's not terribly interesting, but I'm just showing you the pattern for how to create something that we can reuse. Now if you were not using the UMD style, if you wanted to write your code in CommonJS style in Node or you wanted to write in AMD style, then the only thing that would be extra on top of what we're doing here is that you'd need to have Browserify running, and Browserify would take your file, much like templates are automatically converted, Browserify would have a watch that would take this file and automatically convert it to something that would run in the browser. I just didn't want that step involved in our thought processes today, and that's why I've chosen the UMD, but there's really no difference in terms of the concept of what's happening on the inside. So we need a public API to express that, or expose that function, so we'll call that public API random. Now, I want to use that information on both the server and on the client. I have a module now that's being loaded into my server, but I actually want to invoke it and use it. So I'm going to come back to the server.js file, and I want to set up a--- trying to figure out the best place to put this. So I think it's going to go right after loadPage. So right before the default route we're going to make a new route. Essentially, we're going to make a Foo API, a Foo API call. So I'm going to say routes.push, put in my little comment, and then this route is a function, which we'll call the FooRoute. Takes a request object and a response object. This is exactly the same sort of thing you'd do if you were going to define a new route with Express or any of those other frameworks. You'd have to do some sort of middleware handler for it. So that's what we're going. We're making a little handler, or a little middleware for it. Now, I need to figure out if the request that's come in is one that I recognize as being something that I want to do. So I'm going to say if req.url, that's the incoming URL, if it is equal to /Foo with a capital F. And for just good measure, well, no, no, no, let's just be simple, req.url if it's /Foo. So that means we recognize that this is a route that we want to handle. So what I'm going to do then is say--- and I'm going to invoke and use my Foo module. So I have a Foo there that I can just say Foo.random on. Need to pull out a number. Since this is an API request, basically what I need to do is package it up as a JSON and send it back to the server, I mean send it back to the browser. This is all Node stuff, so basically what we're going to do is say res.writeHead, and we want to give it the 200 status response, and then we want to give it a Content-Type header of application/json. And then I want to say res.end, and the final data that I'm going to send along, I'm going to stringify an object, which has one property in it called answer that has the value num that I created. Is everybody following? So that's going to package up a JSON object with one property in it that has the response that we got. Now, I made this simple. This was a synchronous thing that I could answer because it's just random number generation. Had that needed to be something like a database request, which many real API calls do, we might've been calling off to a Foo module and asking it to do some stuff and waiting for it to respond. And it's that asynchronous process that we'd want to invoke something like a promise system so that it was clean and clear for us instead of doing a bunch of nested callbacks, a promise system. So if instead of getting num back I had gotten a promise back, then I would've said something like .then, and this code here would've been inside of my .then because it would've been, I would only want to run this when I was finished with the promise. But we're keeping things simple. We're not doing an asynchronous module at the moment, so I just can manually get that random number right away. And then these three lines of code are really, I mean these four lines code are really nothing special at all. That's exactly how Node does it. It's exactly how any framework out there sends out their responses. So the code from lines 186 to 189 is code that doesn't need to be shared with a browser because it doesn't even make any sense in a browser context. Talking about status codes and header management. None of that needs to be. But if there was something that we were doing there that we would want to share, we'd want to offload that into a module like we've offloaded Foo. Does everybody see that? So you want to look for places where there's something that does make sense to do in both and not repeat yourself. And the basic way that I'm suggesting you go about that is whenever there's something that you want to do in multiple places, that is both places, put it in its own module and do it like I just showed you how we did that Foo. Put a little wrapper around it, or invoke Browserify, or whatever, but put that code inside of its own module. Here we just have this one touch point, this Foo.random that we want to get. So we've essentially made ourselves a route for an API endpoint. But I want to also--- Actually, for now we'll just keep it simple. I keep trying to make it more complex. For now we'll just say our server uses Foo through an API call. Calling the API Let's go to our about.grips.html. We're just going to be silly about this particular page. I'm going to take out that message stuff that I was doing. In fact, let's just take out the partial entirely because that's more complexity than we really need right now. But what I do want is I want to be able to do, I want to be able to have like a button that says gimme. We click this button; we want it to give us a random number back. And I'll give it a little hook that I can use for my JavaScript. I like to use the rel attribute. Some people like IDs. I'm going to use js-gimme. And then I'm going to do one other thing in this little element. I'm going to put in a checkbox--- (Typing) ---with a label. (Typing) And let's start off with our checkbox being checked, so we'll start off by defaulting it to local. So it's just some simple basic HTML stuff. You're terminating your label with an a. With an a instead of a label. Thank you. Alright, now we haven't used any of that code yet, but let's just double-check to make sure I didn't fat finger something. Let's refresh our about, and we see in fact a Local checkbox with a gimme button. It doesn't do anything yet. So how do we make that gimme button do something? Well I also have this architecture set up that it will automatically try to load a JavaScript file in the same name as the HTML file that's been loaded, if you have the file existing. So if we open up the web, js, pages, index.js file, remember that one that we ended up making back to empty, if you open that one up and it's empty, and then we do a Save As, and we save that guy as about.js. And the only thing you need to change in here is make sure that the URL that it's mapping itself to is the same URL as the page. It's just a bunch of conventional stuff. A lot of frameworks use convention, so I'm using some conventions here. Now, my init function is the one that's called after my page has been loaded, either pages loaded from the server or if it's been rendered client side through single-page app. So this is the code where I want to do my main stuff. I want to attach an event handler to that gimme button. And I'm going to use jQuery because jQuery's already something that's being loaded and available in my page. So I'm just going to say rel=gimme. That's the element that I specified in my template. You said js-gimme. Did I? Thank you. Js-gimme. I'm going to attach a click handler. (Typing) And on that click handler, I want to then look at the checkbox, so I'm going to get a reference to the checkbox. What did I call the checkbox? I literally just called it local without the js. That's super confusing. I'm sorry. So local without the js. Let's change that so we don't confuse ourselves. So change it here, and change it in your template. So your rel value is js-. Alright, I'm going to reference to that checkbox. And basically, if the checkbox is checked, so I'm going to say if local.is checked, then I want to invoke the Foo module locally. Now I know I need to load up the Foo module into the browser, so I'm going to pause here and open up the load.js file. You'll notice load.js is already set up to load all of my scripts, and it's doing it all in parallel and setting things up in the proper order, so I want to find an appropriate place here for me to load up my Foo.js module. So probably towards the bottom because it's not being used by anybody else in the stack, so this is probably as good a place as any to load that module in. So I just add in a script call to load the Foo.js module. This is not terribly that much more different than if you were listing this dependency out in some file and having AMD load it for you. I'm just using script loading instead of module management. So that's all I need to do to make sure that my Foo.js module is available to me in browser. So what do I need to do? I need to alert because I'm going to be real simple about it, just alert Foo.random. Now what if it's not checked? If we uncheck that box, what we want to do here is instead of using the local one that's in the browser, we want to make an API call to the server. Remember we set up our API route. So here I want to make an API call to the server, which, by the way, it's going to use the same Foo module. It's going to use it in its instance on the server. So I'm going to do a jQuery ajax call, and the URL is /Foo, and I'm going to tell it that I want it to give it back to me--- I'm not going to tell it anything, so I'm going to expect that it does the JSON parsing for me because jQuery automatically does that. But then I call a .then, and the response that we're getting--- Just for good measure, let's make sure we keep this separate. So in my first alert, I'm going to say that the answer came from local, and in this alert, I'm going to say the answer came from Remote. Oh, not Foo.random. We're going to invoke resp.answer. Now obviously, if I wasn't trying to keep things simple, we wouldn't be using alert boxes. We'd be probably doing something like re-render a template partial in the browser and stuff the answer in there, which is easy to do, but I'm just cutting out those sorts of steps to keep things simple. Okay, so this should work now. These are all the steps that are necessary for us to make an AJAX call to an API. The last step, I think, is we need to restart our server instance. So, if you're using an environment where the shell script is working, the shell script will automatically restart the server; otherwise, you might need to use the forever command to kill it first. But this first stops and kills the old server, and then it starts up the new server for us. And if I haven't messed anything up, hopefully we should be able to load up this page. I'm going to open the Console just in case, in anticipation of me having broken something, which I usually do. Let's try it. Let's call the gimme while the local checkbox is still checked. And we get an immediate answer from local. I'm going to look at my Network tab because I want to verify that if I uncheck the Local box and I call gimme it made a Foo call to my server, which invoked that API route and used the Foo version of the exact same, or the server version of the exact same Foo module, sent the answer back to me, and I got it. Now, we could have done the Foo module instead of making it an API. That was just a simpler way for me to illustrate. But a much more realistic way for me to do this is like what I did in the secure phrase site. I set up a route where if the JavaScript was broken and you clicked the submit button on that form, it submitted a page, it did a post of those form data, and it grabbed a local version of the page, it rendered a local version in the server of that page, and dropped the data right in. That's a much more realistic way of how you use a module in the server versus browser is invoking it with rendering, but we've just kept it simple and just done things with alerts. Rendering on the Page Let me just give you a slightly little bit more practice by working with the template engine in the browser. So let's go to our about.grips file, and let's define ourselves a little thing like, let's see, actually, let me do it this way. Let's say that we want to include a partial. (Typing) Let's define that partial down here. (Typing) An example of shared form validation. Let me see if I can come up with something. That's a good suggestion. Let me see if I can come up with something that won't be too complex. Okay, the define partial here--- I'm sorry, we need to give it the ID answer. Now inside of here, we want to have, we'll make a div with a rel attribute of js-answer. And what we want to do is include inside of that div--- Can you increase your font size at all? Yeah. Is that better? I think so. Alright, so we want to include, so insert. Now in grips, the way that you get at your local variable context that you can insert from, your $., and then I'll assume that there's going to be something called answer there. So we'll pass in that as some data that is able to render. So if we load the about page and there is no answer there, then obviously it's just going to end up rendering an empty div. But what we're going to take advantage of now is our ability on the client side to re-render that partial and replace it. So I'll come back to my about.js, and let's get rid of this alert stuff. What we want to do now is let's make ourself another function called renderAnswer, and we want to call that directly here, and we want to call it here with resp.answer. So, how are we going to render this answer? Well, we're going to call View., and let me look it up. I forgot what the method name is. Get.PartialHTML. There we go. So View.getPartialHTML, and what I want to say, the way I'm going to reference it is this is about template, and then the name of the partial, I separate it with a pound, the name of the partial was answer. It's the thing that we created. And then I'm going to pass it some data, and the data needs to have, that object data needs to have the variable that we're expecting, which is our answer, so we just include that. So that's all I need to do to invoke grips and have it re-render just that template partial, including in the data that I just grabbed out. And then I'm going to invoke some simple jQuery here. I'll pull, I'll get a reference to that js-answer div that's sitting there, and I will replace it with the HTML that I just rendered. So I'm going to take a div that I just re-rendered using the template engine and replace it with the new, I'm sorry, take the old div and replace it with the new HTML from the template engine. So let me just stop and say the reason I'm doing this is because I genuinely believe, and this is not just about this project, it's in general, I don't think that we should be writing JavaScript to manually manipulate contents of DOM elements like saying .value on some input box or something like that. The way that I approach updating my page is very actually similar to what they're talking about in the Ember Glimmer thing that I'm talking about. I figure out which partial is the smallest partial that needs to get re-rendered with my new data, and I re-render it, and I just replace wholesale the DOM element. And if I need to work with event handlers, I'll rebind my even handlers. But you'll notice that I don't have a lot of deep code that knows about the DOM structure and deeply knowing about those things. I just say just re-render the template partial, whatever the contents of it are. Okay, so we've changed our template, we've changed our code to use the template, and if I'm not forgetting anything, I think all we need to do is just simply refresh our page. So it starts out as undefined, and if we then do--- That didn't seem to work. Did I get an error? Okay, let's do some JavaScript debugging. There we go. Now it's getting the HTML in the right spot. And we'll verify that it still works even if we do things remotely. Still makes API calls and grabs the data and drops it in. Shared Data Validation Somebody asked in the chat how could we do something with some shared data validation code, so let's try that. Hadn't thought about it, but we'll just on the fly try to figure it out. So, I will take my Foo.js module, and I'll make another module that I'm going to call validate. So I'll just say Save As Validate.js, take out its contents for now. Make sure to update the name there. Alright, let's start first by integrating it into the server. We could start either way, but I'm going to integrate it into the server first. So I'm going to go back to where I'm listing my modules here. List another one called Validate, and then I'll come down here and load up a Validate module. (Typing) So now I have access to that Validate module from inside of my code. So let's put some validation into our API call. Let's actually send in some, we'll need to send in some data and validate that the data that we're sending in is correct. So I'm trying to think on the fly what kind of data would be appropriate. Let's think that we need to pass in two pieces of data, a min and a max, and they should be numbers, and the min should be less than the maximum number. I'm just making up some data inputs that we could do some validation rules against. So, we'll assume that the request URL is going to receive this information through a get. So we're going to, instead of wanting saying equal to Foo, we're going to want to say the way we test this URL is to put in a regular expression. So the URL needs to start with /Foo. Now I want to parse out the parameters that might've been on my get API, so I'm going to say data is equal to, and I've got a module already loaded in called url_parser here, so it's already going to handle that URL parsing for me. (Typing) And I think just req.url. Alright, so that data's now going to be an object with whatever my get parameters on my URL were. So now we're expecting that there should be a min property and a max property, and we want those to be validated. So what we're going to first is we're going to say--- let's just assume our validations here are going to be synchronous, but you could do asynchronous validation if you invoke promises. So we're going to say we're going to invoke our Validate thing, and we're going to say checkMinMax, that'll be the method that we call it, and we're going to pass in data.min and data.max. So if that check succeeds, then we want to do this work that we were doing before. I forgot, by the way, it didn't bite us before, but I forgot that we want to always return true if we have an affirmative answer to an API request so that the 404 doesn't try to play in. But if the validation fails, then I want to do--- (Typing) Let's send back a JSON response. (Typing) And I could've pulled that error message from the validator, but I'm not going to go to that step. So let's just, we'll ask Validate.checkMinMax. It should give us a true or a false. If it's true, we'll proceed and respond with an API request. If it's false, we'll let the browser know that there was a failure by sending back a JSON object with an error in it. So now let's write that validate rule. We're going to have a function that's called checkMinMax. Takes in a min and a max number, and it, the first rule that we'll say is if--- Don't you need the data value? What's that? Don't you need the value you're checking? What do you mean? Min/max is a bound right? Yeah, but those are the things that we're passing in. We're going to use min/max to constrain our random number. Okay, got you. So we're checking to make sure that min/max is what we want it to be. So let's say that, just for simplicity, we're not going to do data transformations here. You could've done data formatting on the inbound request, but let's just do our data formatting in here. We'll make sure that min is definitely a number. So there's our coercion playing in. Make sure it's definitely a number, and make sure max is also definitely a number. You typed min. Oops. Alright, so the first way that this is going to fail is if max was less than min. We should respond back nope, that's not good. So we can just do a return false rather than sending an error message here. But that's one way that it should fail. And let's say that another way it should fail is if min is less than 0. That's also a failure case. So let's fail the validation there. And if max is great than 100. Just making stuff up. So those are our three data validation rules. Now, the point I want to make about data validation that we're going to share in this way is that this is essentially stateless data validation. We don't need to know anything about our back-end state to do this. So checking to see that an email address is well formed is a stateless validation. Checking to see that an email address is unique within your system, that's not stateless, that's stateful, and you can't really do stateful validations entirely in the browser. So we're constraining ourselves. The shared data validations are the ones that are stateless. So if all of those pass, then we just simply return true. Now this function as written does not care in any way, shape, or form what environment it's running in. It's just a data thing. It just does some data checks. So we're passing in a min and a max, and it's just going to answer true or false. Let's expose that on our public_api. Here's how we're reusing it on the server. Let's just make sure. So Validate.checkMinMax. The min and the max should definitely come in correctly, so that should work. Let's actually use those though to actually constrain our Foo.random number. So let's start out num being that random number, but that's a floating point. So if we said num times 1E9, which is a really, really big number, and we say Math.trunc, so that truncates it, so now we have a really, really big random integer. And what we want to then say, the way that we constrain it to a min and a max is that we're going to do Math. I'm sorry. We're going to take that number that's been constrained. We're going to mod it by data.max. We're going to mod it by the subtraction of those, so data.max - data.min. So if I said that the minimum should be 5 and the maximum should be 10, we'll subtract those two. So we're going to mod our big number by 5, so we're going to get values from 0 to 4, and then we're going to add back in our data.min. Don't worry if that math sounds kind of crazy. I've just done it a bunch of times. That's how you're going to constrain a random number to a particular range. So now I'm going to say that's my new num. (Typing) So now instead of sending back some kind of floating point thing, I'm sending back a piece of data that has definitely--- Now actually, now that I'm thinking about it, that logic is something we want to do in both places. We want to do that on the browser and in the server, and here we've constrained it to only happening inside of our API handler. This is something that the Foo.random method should do. So let's take that code actually, the code that I just wrote, and let's put it inside of Foo. Let me open back up Foo. Let's say that the Foo.random takes a min and a max. That's different than what the Math.random takes. So let's put this logic here. Let's say first that num is equal to Math.random, and then let's say return this stuff. And we just need to update it so it's not referring to data.max and data.min anymore. The benefit of our data validation rules are we know that max is already greater than min because we've already validated that. We would not have gotten to this point if that validation hadn't already happened. So now it's going to return me back a random number that's constrained to a particular integer range. (Typing) Using the Validation Module So now we want to do that same kind of check and call logic in the About, but first we need to give a way to specify those. So let's come to our template, our about.grips template, and let's add in a couple of input boxes. (Typing) So we've got two input boxes that you need to be able to set some numbers into. So in our init function, this call, this function's already starting to get long, so I'm going to refactor by pulling that out. Somebody said Foo.js is wrong. Yep, it does. Good catch. Thanks Vincent. We would've found that eventually I'm sure. Alright, so I was pulling out that function, and instead of using an inline function I want to make that its own thing because I'm going to be adding stuff to it. (Typing) Okay, let's get our min and our max out. (Typing) First step before we try it make the request is we want to do our validation, right? So I want to invoke that Validate function. I want to say if Validate.checkMinMax. Question is can I share all this code that I'm writing? Absolutely. We'll make this available as well. You're not passing in the actual values. You're passing in the--- You're right. I need to call .val here. (Typing) Alright, so if I'm local, then all I need to do is pass those locally, but if I'm doing an API, I need jQuery to add that data on. So I'm going to set up this ajax call with my data as my object min: min and max: max. (Typing) And jQuery should take care of packaging up this data object as the get parameters, sending that along to the API call, of course, which our server code that we're already written will parse that out. If I'm not forgetting anything about jQuery at least, that's how it should work. So, we are using the exact same Validate.checkMinMax rule set in both places, and the only differences in code here is that in the DOM we have to deal with DOM elements, and on the server we're dealing with request URL parameters. So those parts we don't share, but the part, the main meat of it, the validation rules are hidden away inside of our Validate module, and we're just going to share that thing in both places. It may be minor, but if you're doing it locally, you want to check the min/max, but if you're doing it remotely, wouldn't you want the remote side to do the check? So that's actually a great point. Most of the time when people write apps, that's a really good point, segue here, most of the time when people write apps, they actually want to invoke the data validation in the browser so that they can give an immediate response to the user without waiting for a roundtrip. So here we would want to validate first in the browser even though we know the server is also going to validate. And the reason for that is I'd rather pay the penalty of validating twice and letting the user get immediate feedback. If you didn't want that, if you literally just wanted the server to do it, then there wouldn't be any need to run it here, and you could throw an AJAX request against it, but the difference then would be they'd get immediate errors in a local case and non-immediate errors later. Yeah, I get that. So typically people do run data validation rules in the browser before sending the server. Your example though isn't ever going to hit the remote side validation. It'll just always be true. Except for the fact is somebody tried to hijack my app and pass data, again, that's why we have to--- what's that? Are you going to hijack your app? We can try. I can create a get URL that tries it, right? But the point is we have to validate it in both places. The server has to always validate because it can't trust that the browser did validate. We're validating in the browser so that we can give an immediate response. So if we didn't correctly pass the validation, we do want to give an immediate response to the user. So what I'm actually going to do to give an immediate response is I'm going to reuse my renderAnswer just so I don't have to do any extra work here. I'm just going to reuse my renderAnswer--- (Typing) and I'm going to render my error message directly in the same place that that random number gets through in to. So a bunch of different moving pieces. Hopefully all of these pieces--- I'm not thinking of anything that I've done wrong, but obviously there's a pretty good chance that something's broken. But let's just try it. Let's restart our server. We're only restarting our server because we actually made changes to the server code. If everything that we changed was purely browser side or template related, we don't need to restart the server at all. We just need to refresh the browser. So I'll be optimistic and close my Console. Uh-oh, something failed. Probably a good sign that something's wrong with my--- Look on your first shell. No, I've got a problem here. No, my first shell is my watch on my templates. But this is why I have a server log. It's telling me that I got a problem. What problem is it giving me? Server line 188. I'm missing a parenthesis. (Typing) Probably a good idea to check that server log before just assuming that things are working, so I'm just going to 0 it out for now. And then when I restart my server, I'm just going to watch the log. Okay, so I'm not getting any errors thrown. That's a better sign. Let's try to reload here. That was an easy fix. Alright, let's go to about. There's our input boxes. Now, we have not entered anything in yet, and we know that these empty strings are going to end up getting treated as either 0s or as NaNs depending on how that coercion ends up happening. So if we pull out the value of an input box, that ends up with an empty string, which we know that on our number coercion inside of our validator that's going to end up coercing the empty string to 0 and 0. So we would intuit that we would expect if I just tried it just as is, we'd expect a failure. Is everybody following me? We'd expect to get an error message. So let's try it. It didn't work, so what did I miss. Validate is not defined. That's interesting. So it's not finding my Validate module. I forgot to load it. Duh. Let's try that again. We're assuming that we should get an error here. We didn't get an error, we got a 0, so let's do some debugging. Debugging The first step, I know I'm in the local path here. Let's see, about.js. So let's set ourselves up a breakpoint here, make sure that--- Actually, that's not going to be terribly helpful. Let's set ourselves up a breakpoint inside of the validator. (Typing) Normally I'd do that inside of my thing. I'm not really sure. I think it might be my cache busting or something. I'm not really sure why Chrome is freaking out on my local debugging. Let's check and see what we're getting in. We got in a 0 and a 0, which is what we're expecting. Let's look at those rules. Max less than min, which it's not. Min less than 0. Oh, so I intuited wrong. Actually, that should pass. So we probably should add ourselves an extra validation rule. So my bug isn't necessarily in. It's just that I'm missing a validation rule. We should probably say if max less than or equal to min because that's a case that we probably don't want, a min and a max equal to each other. That's not going to be very helpful. So let's just try that. I'm going to reload here. Since I changed a file that is going to be used on the server, I'm going to want to restart my server. (Typing) There we got our validation rule. Now, we didn't actually handle. I need to handle that. This is a detail I forgot. We didn't actually handle what happens if the AJAX response gives us an error back because that's one of those cases where validation could fail at the API level and not here. We know that won't actually happen, but this is a case that we should handle just in case something was broken in the browser. Maybe you had an old version of the validate function or something like that. So we want to handle the .fail case. Actually, not the .fail case. That's still going to be success, but we want to look at the response to figure out whether it had an answer or an error in it. So if it had resp.answer, then we'll render the answer, and if it had resp.error, we'll render the error. We can't really test that that stuff's going to work without trying to break our app, but that's just a piece that I don't want to forget. Okay, so let's try 3 and 10. I got back a random number, but it's not constrained properly, which lets me know that I wrote something wrong about my constraints logic. So let's go to my Foo module. So that would have been this number mod 7 plus, or mod 8, which is 0 to 7, plus the min of 3, which should've constrained us between 3 and 10. Why is that not working? (Typing) Let me verify that we're not getting something weird coming in. (Typing) Ah, we're being way too trusting about the inputs. We're converting them to numbers for the validate purpose, but we're not converting them in the Foo module, so we should be doing that. We should say min = Number(min), max = Number(max). (Typing) Let's check that. Alright, that looks better. So let's take out my debugger so I'm not going to be annoyed over and over. Appears to be working there. Let's try something slightly bigger like 10 and 50. What happens if I make the max too big? My validation rule fails. Now, let's switch this to Local. Let's give it something. Let's just verify that--- I mean to remote. Let's verify that we're going to in fact still get stuff working if we send it off to our API. Let me restart my server because I think I might've made changes that the server needs to have. (Typing) Alright, let's go between 10 and 40, and let's see what the server has to say. So it give us a 39, 38. What happens if we give something bad to the server? There we got our error message back. Actually, that error message didn't come back from the API. That was our local validation. We can very easily break our data validation to verify that the server is still backing us up, which will be the last step, and then we'll wrap for the day. In our about.js, all we need to do verify is just skip the local validate step entirely. So we're not going to do any local validation, and we're going to now try it in a non-local case and verify that the server validation is still working correctly. So 10 and 40 still works, but 10 and 400, we got back the failed from our API. Alright, so let me just recap, and then we'll finish up. I'll make sure there's--- Is there any validation preventing 0 and 0? Yeah, the validation of that they can't be less than or equal to each other. That's the test. Key Takeaways Some principles to take away here. In any place where I found code that I wanted to share it between the two places, the best way to do that was to organize it into a module, and I chose the UMD style just because it doesn't require any other moving pieces. It's just a file that can load in both places. But you can easily offer them in whatever module format you like and use something like Browserify. And I loaded my modules into my server using require, like we see right here. I'm using the require to load it up. Now, I didn't really talk about this, I kind of glossed over it, but you'll notice that I was just automatically putting these shared modules in a location where I knew I'd be able to load them in the browser, and then I just when and got them from the same location on the server. That may or may not be the appropriate approach for a real production app. In fact, more likely, you're probably going to have some sort of build process that's taking your files that you want to share, and it's packaging them up from some non-web associated location and making a copy of them over to the web-accessible location, my web directory, for example. So I probably have some sort of Grunt or gulp process that was running that is minifying my files and moving things around and doing transpilation and all that, and one of the things that it would do, it would take my Foo module from my, say, main root or some module subdirectory, and it would prepare that in whatever way was necessary, and it would copy it to the web-js directory. And therefore, my require statement that's happening there, I would not be requiring it from the web.js directory; I'd be requiring it from its normal location. But to keep things simple, I just had one file and one location. To set up our route, I didn't have to think about any of the other mechanics of how routing was happening because that part's already been written for me. And exactly the same way as you would set up one of those sorts of things in Express or any of the other frameworks, we just wrote ourselves a function. And the function here, its goal, is to figure out in whatever way is necessary whether it wants to handle the request or not. Here I wrote a regular expression. There's lots of modules out there, not big frameworks, but tiny little modules that let you do smart things with routing. They'll automatically kind of author your regular expression or whatever you need them to do. And so if you didn't want to write your own regular expressions, you could pull in a module into Node that would do that. We handled this, and we told the router that I had written, we told it that we'd handled it by returning true. If we don't return true, it would end up throwing it to a push. So guess my last check would be what happens if I try to call localhost. We'll do this, look at my Network here. What happens if I try to call localhost port 8050, and what happens if I give it a Foo that has no URL parameters on it? We'll there's our JSON response coming back. I'm not sure why it said null, but that's our JSON response coming back. But what happens if I do a URL that is not even recognized? Oh, I have to give it one that actually would be, would fail the regular expression. And you see I get that 404 route that I set up. So instead of having a 404 route that just gives a blank page, you could, of course, load up a real 404 page and throw it out in exactly the same way. So those are the main principles that I use when I'm trying to share code between them. And the overriding design principle I have here is starting with nothing and only doing the bare minimum in any given situation instead of assuming that I need a really super complex framework with tons of bells and whistles and then spending days and days reading through their documentation trying to figure out exactly how to get it to work. I feel confident enough that I can just write if statements, or for loops, or functions, or whatever to do the things that I need it to do. And you may not already feel that comfortable, but it won't take a lot of practice if you practice with that shell app that I gave you and you tried a couple of things that we did here. If you tried that two or three times, you'd very quickly get to the point where you'd have that same kind of confidence. I can write the JavaScript in the places that I need to make it happen. Thankfully, I didn't get bitten by too many errors that weren't that difficult to track down. I wish we'd had a little bit more time. We probably would've talked a little bit more about Node debugging. There's lots of great tutorials out there on the web. So if you go through NodeSchool, they talk about how to do Node debugging. You can do either command line debugging with Node, or you can do remote debugging from something like your Chrome console or whatever. So that would've been a way to track down some of our Node errors if we'd been having those. Final Questions Let's see, are there any last questions that I haven't answered about this exercise? Not about this exercise, more in general, testing. Testing. Yeah, obviously that was way outside of the scope of things that I wanted to do here, but I do typically write a smaller subset of unit tests. And what I would look at in a shared environment like this is the stuff that I want to unit test is the stuff that's shared because that's the stuff that I know can run agnostic of its environment. So that validator rule, for example. That's a really easy thing to unit test because I know I can just stuff a bunch of data in it, and I'm asserting that I'm going to get the right answers out. So I typically, again, I know that a lot of people have their different opinions on what test frameworks they like or whatever. There's a real simple one that's still powerful enough for most of what I use, and that's QUnit. And I use QUnit to do my basic assertions of little unit tests like that. Most of the time I don't even need the asynchronous capability. If I need an asynchronous test, Mocha is another suite that's maybe a little bit better at doing asynchronous testing. But I don't go to the real extreme routes that other people do. There's a lot of great testing frameworks out there. But I'll do a QUnit for a basic set of unit tests, and then I will do regression tests for my integration in my browser, and that'll test all the other paths. Kind of the full package all together. Again, minimal. I start with no tests and work until I have confidence on it instead of assuming that I need to write lots and lots and lots and lots of tests. Okay, I'll just leave you with this. JavaScript's really awesome, but it's even more awesome when you can use it in both places. And I hope that what you got out of this last bit of our talk together is that once you get confident with all of JavaScript, once you spend a little bit of effort learning things, learning things like coercion and the other parts of JavaScript, it's a really easy thing to write a basic Node server that does the things you need it to do. You don't actually need to spend a lot of time being an expert. I am in no way, shape, or form a Node expert. On the whole scope of things, I'm not actually that high on the ladder scale in terms of my Node skills. I'm competent, but I'm certainly not some kind of crazy hack or expert or whatever, but I know enough about JavaScript that I can get done what I need to get done. And that, I hope, is the biggest message to takeaway here. Learn JavaScript, and use all of JavaScript, and use JavaScript across your whole app. Thanks for being here. It was an honor to be here. One last quick thing just to remind everyone that this is my contact information, and I'll just leave you with that to say--- Oh, is there a question I missed? Which direction would you go if you were to scale up? I assume the question means if I needed something more frameworkish, which direction would I go? The next step up is I'd move to Express or maybe Koa. So I'm not sure if that was exactly the question. The other question was can you share this code? Yeah, absolutely. The current state of things, as I just wrote it, that'll be part of a zip file. It'll have, I'll send out a zip file that has the corrected stuff that I messed up plus this new stuff, so that'll be sent out so you'll have this copy of this code. But it'll also probably end up on GitHub pretty quick, but I'll send a zip file to you too so you have it right away. Okay, well, what I was saying on this last slide, as an opened-ended invitation to anyone that ever takes one of my workshops, I mean it when I say that it's impossible for you to have completely fully uncompressed everything that we talked about today. There's a lot to go through. So I encourage you not let this be the last moment that you ever look at these exercises or look at the slides. Go back over them. Go back over your notes. Try the exercise stuff that we did from scratch. Try it, and you may need to try it a few times. And it's quite likely that you're going to run into some problem or frustration, or question, or something that we missed. So I want to invite you to feel free to reach out and ask questions from here on out. There's lots of different ways to get a hold of me. Tweet at me, send me an email, whatever. All the time I get emails from former attendees of workshops, and I love helping people. So if there's anything that I can do, more than I've already done, to help increase your awareness, you're learning of JavaScript, and your appreciation of this platform, feel free to let me know. It's been an honor being here. Thanks for all your all your time and attention. Course author Kyle Simpson Kyle is a freelance developer based in Austin, TX. He runs several open-source projects (such as LabJS), writes books, and speaks at meetups and conferences. Course info LevelIntermediate Rating (20) My rating Duration5h 6m Released23 Feb 2018 Share course