FREELessons: 29Length: 8 hours

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

3.1 Slides and Structure

You should have a fairly solid understanding of the basics at this point. Today, we're going to kick things up a notch. We'll learn how to use jQuery's slideToggle and fadeToggle methods to adjust the display of an element.

In the process, we'll also focus on the structure of our code. Massively indented code and nested callbacks can be considerably difficult to maintain. We'll fix that!

3.1 Slides and Structure

[NOISE] Hello everybody my name's Jeffrey Way and welcome back to 30 Days to Learn jQuery. So today we're going to take another leap forward. We're going to take a look at fix. How you can use fades and slides. But we're also going to focus a good bit on structure, and this is something you'll especially wanna pay attention to. With jQuery, it's very easy to have hugely indented code. That makes your projects very difficult to manage when you have all of these callback functions. So that's something we will also handle in the process of today's demo. Now here's what we're going to build. We have a simple post, and we want to have a button at the bottom for the user to contact the website owner. So you can see we have this Contact Me button, and when we click on it, a contact form slides down. And then, there's also an x button where they can slide up. But even better, we'll offer ways to configure this. So, for example, if we go back to the code, and I scroll down to the bottom, you'll see that we can specify some configuration settings. For example, if I would rather fade this image rather than slide it down, I can use fade toggle. And we can say, I want you to do that over the course of two seconds, which is way too long. But just for the demo. And if I refresh the page and I click on it, you'll see that that fades in over two seconds. So, it's always nice to allow the user to configure the settings just a bit. Okay, and as always, we're going to begin our JavaScript from scratch. So, I'm going to select all of the code right here. And we're going to get rid of it. And what that's going to leave us with is what you see right here. And, this is always important to remember. Don't immediately jump into the Java Script cause remember some people will be browsing your website with java script turned off. So, do you want to provide a contact form for them? Yeah, of course, you do. So, make it look good first and then upgrade to using JavaScript effects. So, here is our base layout. You can see we have our post, and then at the bottom, we have a styled form. If you want to take a look at that, its simply a form and I just have a little bit of css at the top that we'll go over shortly. Nothing big to worry about here. Now, the first step is to determine whether we can use JavaScript. Any JavaScript is read then the user has JavaScript turned on. So why don't we do this? Why don't we apply a class to the HTML tag write up here? So we'll do that right at the top. Once again, I'm gonna use a self invoking anonymous function just to keep from creating lots of global variables. And next I'm simply going to grab the HTML element. I'm going to add a class and we'll give it a class of JS. So now, we know if I open up the web inspector if the HTML has a class of JS, then JavaScript is available. If it does not, then it's not available and now we can use that within hooks and our CSS file. If I scroll to the top of my Excel sheet, you can see that we're styling the contact form, but then if JavaScript is enabled we're going to make slight tweaks. So I'll hide it. Remember, if we come back, it's displayed down there. But now, I'm gonna use that new JavaScript hook, and I'm gonna position it at the very top and make the width equal to the width of its container. And for now, I'll make the display equal to block. Come back, and now can you see that it's been placed at the very top of our page, and then we hide it, because we don't want to see it right now. Good. Alright, so we're ready to get started. If JavaScript is disabled our form will function fine. If it's enabled we can add a little bit of effect to it. Now the first tip is to provide a little bit more of structure for applications, even though this is very simple, don't get an a have of just creating all of these indented call back function, that's really difficult to work with. So, we will create a parent object and we will call this contact form. I'm gonna make that equal to an object literal. Now first, we need a method that we call that sort of gets the ball rolling. And this is most often called Init. If you're familiar with object oriented programming, that would be the same thing as your constructor method. So we'll say init is a function, and this method, as I noted, gets everything moving, so at the very bottom we're gonna call it contact form dot init. Hopefully that makes sense. This pages runs. We create a parent object, and then we call its first method init, which gets everything started. Now, within this method, the first thing I wanna do is create a button the user can click on. That will toggle the display of that contact form. Well, we know that we can create HTML and throw it into the dom really easy with jQuery. So we'll create those tags. And then we'll pass an object as a second parameter so that we can give it some text. And this text will be Contact Me. Now the next step is, I want to insert this button right after if I scroll up. Let's insert it right after the article. So I want the button to show up right here. Well, if you refer to the last lesson, we know that once we have essentially an HTML fragment, we can insert that after the article. So I can do that, insertAfter( 'article '), and if you need to be more specific, you can use an ID on that article, you can use a class,. You could even say article:first like so. So let's save that for now and come back. Reload the page. And sure enough, you can see that the Contact Me button has been added. But when I click on it, of course, nothing is going to happen. So that's the next step. I wanna listen for when that button is clicked. And when it is, I want to display the contact form. Because remember, the only thing that keeps the user from seeing the contact form is the fact that we've set the display to none. That's the only thing. So, when that button is clicked, we're simply going to alter that display so that we can see it. And in the process, we'll add a little bit of effect to make it look better. After we create the button and insert it after the article, then I'm going to attach an event handler. And we're going to listen for when that button is clicked. And when it is, we have a couple of options here. We could pass an anonymous function, like so. And this is what we've done in the past. But again, I want you to be a little careful with this, that it's very easy with jQuery code to see these anonymous functions extending, where your indentation is all the way up here. So many times, you'll find that it's easier and more maintainable to reference a named function or method. So in this case, rather than passing an anonymous function, we will pass this ".show." Now, within the context of an object like this, this is going to refer to that contact form. Now to verify that, let's comment this out and I will "console.log" this. Because this is something that I think is really important to understand. Otherwise, you get really confused with, what is this, in this context, and then this. So if I log this with an in it method, you'll see that it refers to the object. And right now, the contact form object only has an in it method. So let's remove that, uncomment this. And when that button is clicked, we're going to refer to the object by using this, and then we're going to call the show method. We'll create that method right now. And for now, we're simply going to write showing to demonstrate that it is working. I'll click on the button and now we do showing at the bottom. Now, a question that comes up a lot is, well if show is a method, then why aren't we doing this? Why aren't we calling that method. And it's because we don't want to call it right away. If childscript came across that it would parse all of this code and then it would come to this section right here, this.show and it would immediately execute this function. But we don't want to do that, we only want that function to be called on the condition that the corresponding button is clicked. So now, we're going to hard code some things in, just for the time being. I need a way to reference the contact form. And the contact form is stored within a div with an ID of contact. So let's create a variable called container. And we'll simply jump into the dom and grab that div with an id of contact, like so. Good. Now, in this case, we're going to grab the container. We know it's hidden by default, so let's just show it for now. Close this out, reload, and when I click on Contact Me, we're getting an error. Let's see what it is. Cannot call method show of undefined. Now you can see, and I did this on purpose, you can see that this does not refer to what you think it does. You would think this refers to the contact form object. But that's not what it does, because, remember, we listened for a click event and then we called a function. So it's the same thing as if we did this. And we know from previous lessons that within a callback function, this is going to refer to the button that was clicked. It's no longer referring to that object. So, that's why as I noted within a Call Back function or in some other situations, you'll want to refer to it as contactForm, by its name. Okay so, let's back up just a few steps. And then update it to contactForm.container and now let's see if it works. I'll bring this down, click on the button, and now you can see the contact form. Good. That was pretty easy. But now we need a way to get rid of the contact form. So we probably need some kind of close button in the top right corner. Alright, let's add that right now. We'll create a new function, and we'll call this close. And within here, we're going to create a span. I'm gonna give it a class of close. We'll just hard code this in right here, and I'm going to use an x to represent a close button. Good. So now, we've created the span. We're going to append it too. And what will this refer to in this case? And the truth is, this can refer to whatever you say it does. But you have to be explicit about that. So when we call this function I wanna make sure that this is going to refer to the container, or the div with an id of contact. So keep that in the back of your mind. This is the contact div. So we're going to append that X span, or why don't we change it to prependTo, and then once again, we're going to attach an event listener. And we're going to listen for when it's clicked. And when it is, we'll just pass an anonymous function here, and we will simply grab that contact div and hide it. It's showing the user clicks on the X button, so they're done. Now we need to hide it. But once again, you would think we could do this.hide. But we can't do it because we're within a callback function. In this case, this refers to the div with an id of contact. But then we listen for when this close span is clicked and when it is within here, this is going to refer to the span. So how do we roll back and refer once again to the contact div. Well, we know that up here this refers to the contact's div. So, why don't we cache that location. So we'll say var this equals this. And now we know that's the contact div. Then within here, we can simply reference it, like so. This, hide. We showed it, now we're going to hide it. The next step is we need to call this function. So right here within the show method we know that the user has clicked on the button. They want to see it, so let's make sure that we add the x button. And then we display the form. At the top, we'll say contactForm.close. But remember, if we do it like this, this is going to refer to the contact form object within here. This will not refer to contact. It's going to refer to the contact form object. Now, there's lots of ways to deal with this, but for demonstration purposes, how could we say no, within this function, this is going to refer to the contact div rect within jQuery? The way we do that is we use a JavaScript method called call. And this means we are going to call the close function right here. And within here what are we going to use to represent this? Well, that's easy. We want to use, contactform.container and that's all there is to it. Now close is immediately called and within it, this is going to refer to the contact div. Alright. Let's try this out. See if we made any mistakes. I'm gonna open up Chrome Developer Tools, click on Contact Me. And now you can see in the top right corner we have this close button. Now you'll see that we have a little pointer finger there. If we scroll back to the top, you can see that I've styled this just a bit. So by default, without any styling, the close button is going to look like that. But then we simply position it absolutely and we put it in the top-right corner, and then we set the cursor to pointer so that the user knows they can click on it. Now let's see what happens when I click on it. Click and now it hides, pretty easy. Click, Hide. So now that we have the basic functionality in place, we can expand this a good bit to provide a little more effect so it feels like it's sliding down. Within our object I'm going to add a new object within it. And we're gonna call this config. And this is where we can set some base settings. And then later we'll allow the user to override those settings. So we'll say that base effect, and this will be how it's hidden and displayed. I'm gonna use slideToggle. So with jQuery, if something is hidden and you want to display it by sliding it down,. You would use a method called slideDown. And if you wanna hide it using a Slide, you would use slideUp. And the same thing for Fading, fadeIn, fadeOut. Now, if you wanna use the same kind of Toggle functionality that we know we can achieve with Show and Hide. You have the same thing, slideToggle. And then you also have fade toggle. And that means if the element is hidden, fade it in. But if the element is displayed, then fade it out. That's all toggle means. So it's simply a helper method. So within here, I'm going to set the default effect, to slide toggle. Now, rather than using show, we're going to use our effect. So rather than contactform.dot.container.show, we are going to reference slide toggle, and we can reference that by using the array notation. So you may not know that when you have an object, for example, Contact Form Container, you can reference that by doing contactForm.container. We know that. But you can also reference it by doing contactForm['container']. It's the exact same syntax. So, this makes it really helpful, when we don't exactly know what the name is. We can simply reference a variable. So, let's put that into effect right here. Rather than calling the show method, we know that we essentially want to call, slide toggle, but in order to do so, we wanna reference whatever is stored here. So instead, I'm going to reference contact form dot config dot effect. And this will essentially be translated to, slide toggle. Now, we've referenced it, we simply need to call the method. So I'm going to use, an opening and closing parentheses. And we'll set a default for now of 500 milliseconds. And now that means it's going to slideToggle over the course of 500 milliseconds. And we'll get rid of these surrounding quotes. All right, let's try this out. Refresh, click Contact Me. And now can you see that it's sliding down, like so. But if I click on the X, once again, we're still using the hide method, not the slide up or slide toggle. So right here, we can say, once again, rather than the hide method, we're going to use brackets, contact form, dot config, dot effect over the course of 500 milliseconds. Once again, click Contact Me. It slides down. I click on the x and it slides up. It's as easy as that. The next step is, let's provide some flexibility so that when we call the init method, we can specify if we want a slide toggle or a fade toggle. So when user calls the init method. They want to be able to pass an object and they want to say that effect rather than the default of slide toggle I want to be fade toggle. And I want the speed or how long it takes, I want that to be really long. This is too long to every do in your projects but it's helpful for [UNKNOWN] to see that it's working. So now when the init method is called. This config object will be pass, and config will be equal to this. And now we can use a helpful method that's part of jQuery core, where we can say jQuery.extend. And this is pretty neat. What this allows us to do is apply a default object, and we've already created that, right here. So, we are going to extend this.config, and I wanna say, here's my object. Next, I wanna take whatever the user passed within their own object, and that's going to override anything that I have, like so. So that means if we have effect right here, well,. The user overrided that. So I want to replace this object, and now the effect should be equal to fade toggle. On the other hand, if we have speed 500, and the user never passes his own speed, then speed will remain at 500 because the user did not override it, within their object. So it's very simple. This is our target object. Anything right here will override our default object. It's fairly simple. So I'm going to backtrack and we have 2000. We have our default effect that's being overridden right here and now let's see if it works. Refresh, click on Contact me, and now you see as easy as that, we've provided configuration options where it fades instead of slides. And because we've referenced the effects in every area by referring to config dot effect, we don't have to update that in all of these different methods, it'll simply work. Because they're all referring to the same effects style. Now, the last thing we need to do is speed. We do wanna make sure that we don't hard code the speed in, for our demo at least. It's very possible in your projects you don't need this level of control. But if you're building plug-ins in the future, you might wanna do that. So now we can add speed. And I'm going to set the speed to half a second, or 500 milliseconds. And then we simply replace it in each location. Contact form, config, speed. I'll copy that, paste it in right there. And, we're good to go. So now, when I click on Contact Me, that's going to fade in, over the course of two seconds or if we elect to not override the default effect. Then, it will slide down, over the course of two seconds. As you can see right there. Good. Now, of course, you would never wanna do an effect that slow. I usually stick with around 300 milliseconds. One more time, click it and that's pretty snappy. Now, at this point, our effect is done. We just wanna do a little bit of cleanup. Right here in the show method, you can see that gets a little difficult to read, because we are referring to contactForm.container. Contactform.config. So why don't we improve performance a tiny, tiny bit and also make it more readable for us. We'll create some variables. We'll create one called cf for contact form. Next a variable called Container and that's going to refer to contactform.container or remember that refers to the div with an id of contact. And then one more. Once again, this is mostly for our convenience config, and that will be equal to cf.config. Now we can clean things up a bit, and I'll get rid of this and refer to container. Then, get rid of this and refer to config. And the same thing right here. And up here we can replace that with container. That looks good to me, and look how much easier that is to read. One more time, try to make sure it's working. Good. And now, the final step is, when the show method is called, we need to keep in mind that it's possible that the user could click on this button. Even when the form is displaying. In this case, we've lucked out and the form is covering it up. But it's very possible in your project that will not be the case. So we wanna be sure that before we do anything, we wanna check to see is that form already displaying? If so, we don't need to do anything and we can do that really easily. We'll say if container.is, and this is a new method. And this allows us to see if maybe a specific element has an idea of div. So you could say if container.is div, or you could say if container.is container. It's a really helpful method. In this case, we wanna say if the container is hidden and that essentially means display none. So if the container is not currently displayed, it has a display of none. In that case, good. We do want to show it and we do want to add the Close button. Refresh, click on it. It's still working. But now, we've added a little bit more protection, where we're not executing these functions if we don't need to. And now, we have one more thing to do before we finish this lesson. I reload the page and I click Contact Me and I close it. That all seems to work. And even if I do it again, that seems to work. But, come down here. Take a look at the context div, and now you can see, every time we click that button, we are adding a new close span and the reason why it's doing that is because we've told it to. So we need a way to say, if there is not already a span, then add one, but if there already is a close button, we don't need to do it again, because if we do, we're going to end up creating all of these extra elements, and that's not good. So an easy way to handle this is right at the top, right here, we'll say if this dot find a span with a class of close. Remember, this refers to the contact div, so we are saying right here, if you can find a span with a class of close within this div, then we don't need to add another one. So in that case, simply get out of here. Return from this function, and return again means, nothing afterwards is going to run. We're done with the function so we're going to turn around and return. But now, it won't be enough to simply. Look for that span because jQuery will still return something. We simply want to see if the returned object has a length, and if it does that means something was actually returned. So I'm gonna look for length. Another way you could do this would be that, and that means, get the first item from the array, but we'll stick with length, and now let's try it. Refresh. Contact. And, let's make sure. I'm gonna click and inspect that. And when I close it, if we did everything right, we're only creating one. One more time. And now you can see, at most, we only ever have one span, because the first time this runs we say is there a span with the class of close? Nope. All right. Well, let's go ahead and create one. But the next time it's called when that button is pressed, this runs. Is there a length? Yes, there is. In that case, we're done.So, let's return from this function and simply toggle the display. Okay, and we did quite a bit in this lesson. This is easily the most complicated lesson we've done so far. So if that was a little difficult to understand, absolutely go back and watch it again. But, if you were able to follow along, we did a lot of cool stuff today. You learned about how to use the call method, which is really cool to specify what this represents. You learned how to provide some configuration options using jQuery.extend, and you also learned how to provide a little bit more structure for your projects by using an object to contain all of your various methods. And then finally, we also reviewed how you might wanna be careful about constantly using anonymous functions as your callbacks because really easily you can end up with massively indented code once you have four call back functions within each other. And that's way too difficult to maintain. So, if you have any questions and if you are a TutsPlus premium member you can go to tutsplus.com/forms. Otherwise I am Jeffrey_Way on Twitter. And feel free to ask any questions that you might have. All right, I'll see you in the next lesson. Bye-bye.

Back to the top