FREELessons: 29Length: 8 hours

Next lesson playing in 5 seconds

  • Overview
  • Transcript

3.6 Homework Solutions

[SOUND] In the previous lesson I gave you a bit of homework. If you scroll down to the bottom you'll see, tonight I want you to create your own fadeSlideToggle method. That will combine the functionality of slideToggle and fadeToggle. But you may not reference either of these methods directly. Instead, you have to use jQuery's animate() method. When finished, the method should be called like so, jQuery box.fadeSlideToggle. Okay, so I expected you to do that on your own. If you'd like to chime in on the forums, and see how you compared to mine. Definitely do so. But in this lesson, we're going to build this from scratch. So if I go into Sublime Text, we have more or less what we had in the previous lesson. We have our box, but now at the click of a button, we want to implement our new fadeSlideToggle method. So if you go back a couple lessons, you'll know that we can create our custom methods by doing jQuery.prototype, and we're going to extend it with a new one, fadeSlideToggle, and that's going to be equal to a function. Now with this setup, we can grab a collection of elements, and in this case, we're going to grab the divs with the class of box and call fadeSlideToggle. Now in this case though, we do wanna make sure that that only occurs at the click of a button. So let's change that out to button.on, click. Function. And then we trigger div with the class of box. But as we learned in the previous lesson, we want to be careful about jumping into the DOM and grabbing those elements every time the user clicks on the button. So as we've been doing a lot lately, we're gonna wrap all of this within some code. And at the top we will create our box once again, and now we'll reference that exactly one time. So when the user clicks on a button, we're gonna call this new fadeSlideToggle method, and for now, we'll simply log fading and sliding. All right, let's try that out. Open up Chrome developer tools with Shift + Command + C on the Mac, and I'll click on the button. And there we go. So the next part of the homework was, you need to combine the functionality of slideToggle and fadeToggle. So let's go through these one at a time. What is unique about fadeToggle? When you click on it, if the element that it corresponds to is visible, what it will do is it will lower the opacity, it fades it out. And then it hides it. So it adjusts the opacity and slideToggle is going to adjust the height. So if you run slideDown on an element that is 200 pixels high, it will slide from 200 to 198, 97, 96, until it gets to zero and then it hides it. So we know with slideToggle, we're dealing with height. Now, the homework specified that you cannot use either of these built-in methods. The idea is to figure out how you could do it on your own if these did not exist. So we used the animate method. We can refer to this, and that's going to correspond to the div with the class of box. And we begin by calling the animate method that we learned about in the previous lesson. So for now, let's try this out. Over the course of a half second, we're simply going to take the height and we're going to reduce that to zero. That will be our first practice session. I'm gonna close this out. Refresh and I click on it. And sure enough that seems to be working, but it's not going all of the way. And this is going to be due to just a little bit of padding. jQuery has some trouble with that. But I get rid of that. Okay. Well, that seems to be working pretty well. Let's bring that back and now let's try out the other option and that is to do opacity. And we're going to animate the opacity from its current level, down to zero. Let's try that one. Refresh, do that one, okay, and that's pretty cool. So now we're pretty much getting a slide effect and a fade effect. So what if we group these together? Reload, click on it, it slides up and it fades out. Look at that. That was pretty easy. But we have a fade slideDown effect at this point and they're still visible. So if I open this up you'll see that we can still see that box. We really need at the end to add a display of none, ultimately, to get rid of it. So let's take care of both of these. First, rather than hard coding the value in as zero, if you took a look at the homework, you'll know that jQuery offers us the ability to pass a value of toggle to height and opacity. So let's try that out. Refresh. And now we're getting that same effect, but take a look. If I open up Chrome Developer Tools again, you'll see that in addition to toggling those values, we also ultimately set the display to none, so that's really convenient. And then when I click on it, because we're using the toggle keyword, you'll see that it opens it back up. Let's try that again without Chrome developer tools. Close and open. Close and open. So now that we have the basic functionality in place, we can add some configuration options and make sure that it chains well enough. So, for example, by chaining, I mean, once we call our fadeSlideToggle method, we should be able to continue chaining. For example, let's add a class of testing and now open up Chrome developer tools again. And I'll click on the button and you'll see that we get an error. Cannot call method, addClass of undefined. And why is that? Well that's because we ran our method, but we did not follow best practices. We did not return the jQuery object so that we could continue chaining. So when people use our method, they will fully expect to be able to follow this pattern, but they can't. So the solution is always return the jQuery object from your custom methods for your plugins. So now if we try it, I click on it, you'll see that that does work, and we've successfully applied a class of testing. Rule number one, when writing plugins or creating little helper methods like this, always return the jQuery object so that you can continue chaining. Next, let's work on some configuration options. I'd like to be able to pass a speed similar to what we normally do with slideToggle. So ideally I want to pass this value. Okay. Well, that will be represented right here. So we'll set that to speed. And we'll do it right here. We'll replace the hard coded value with what the user passes in. So now if I set a long number, fadeSlideToggle, now over the course of five seconds that's going to toggle its value. But what if we don't pass anything at all? Well, let's see what happens. It's still going to work because jQuery will recognize that this is undefined and it will use its own default value. Now if you'd like to override that, you could say use the user speed, whatever they pass in, or if speed is undefined, or they did not pass anything in, then we'll set a default speed to two seconds. Just to make sure it works. So nothing is passed, it's going to use one, two. Or if we pass something really long, you'll see that it uses our value, and that's an easy way to pass a default. Now in this case, we're going to stick with 500 and we'll set the default to 400. Good. So we've added some configuration options. Well what about a callback method similar to when we do slideDown? For example, when we call .slideDown we can specify a value. You can even specify an easing if you want to use a custom easing method but that's optional. And then you can pass a callback method that will execute as soon as the slideDown has completed. And we should probably implement that as well. So our goal is to do this and when that completes, we'll say finished. And just to make sure that we can tell, I'm going to increase this value to two seconds long. So if we try that out as you might expect nothing's going to happen, and that's because we're building a custom method, so even though we passed the callback, we never triggered it here anywhere. So let's fix that, and I'm going to refer to that as fn. So now we call fadeSlideToggle, 500 is represented by speed, and for the fn variable, that's going to be equal to this anonymous function. So we need a way to call that function when this animate method completes. What we know, that the animate method gives us two ways to structure it. We can run animate then the speed. You could pass easing, which is optional. And you can also pass a callback like this. Complete. So with that in mind, when we only want to execute the user's provided function, we can simply call fn. And we can make this better shortly but, for now, let's see if that works. Refresh and I'm gonna click the button. It's done and we do get complete. Very cool. But, doesn't this seem a little silly? When the animation completes, we run an anonymous function and the only thing we do within that function is we call another function. So why don't we get rid of that entirely and simply reference fn? Now I'll save it. And notice I'm not triggering the function and this is a question that comes up a lot. Why are you j ust referencing the function without triggering it? And the reason is, if we had those opening and closing parens, this closing function would execute immediately as it's being parsed. But we don't want it to execute just yet. We only want it to execute on the condition that the animation has completed. So we store a reference to it. All right, let's try it again. I'll click on fadeSlideToggle. And now that completes. Let's do it the other way. It comes up. And then you can see the number two, which means it was called again. Now here's the final thing we need to go over. What if the user does not pass a callback function? Well at that point, we are referencing fn, but fn is undefined, and we can console.log fn to see that for sure. Refresh, I'll click fadeSlideToggle, and sure enough, you're getting undefined. Now because this value is undefined, it will more or less fail silently, which means we come to animate, and it tries to trigger a callback method, but that's undefined so nothing ever happens. And you don't really have to worry about that, but if you want to be a little more secure you can determine first whether it is a function. And there's lots of ways to do this with JavaScript, but jQuery offers a core method called, isFunction. Let's hunt this method down in the jQuery source. I'll come back, go back to our bookmark. You can also go to, that's a little easier to remember. And we're going to look for isFunction followed by a colon, and here we are. So this method will simply determine whether the type of what you pass is equal to function, and that's what we can use here. So we'll say if jQuery.isFunction and we're gonna pass in fn. Then we'll say, is a function, just for now. So we can see that it's working. Else, console.log and we'll make that is undefined. So let's try that out. FadeSlideToggle and we get is undefined, but on the condition that we pass a callback function. Click on it one more time. We are successfully testing it. And if we refer back to the jQuery source, we'll see that jQuery offers a lot of these little utility methods, isArray, isWindow, isNumeric, isPlainObject, isEmptyObject. So definitely refer to those when you need to determine how to test for a specific type. So in this case, what we could do if you need to have full control is pass an anonymous function again. And then we could say function fn and we can use a little shorthand here and call fn. We can also do and then pass in this, if we need to make sure that we specify exactly what this refers to. So now this will only execute on the condition that fn is equal to a function. It's the same thing as doing if jQuery.isFunction, then do this. So let's try it out. If we did it right, we'll get console.log hi. Close that out. Refresh. fadeSlideToggle. We do get hi. But if we remove the callback function, at this point fn will be equal to undefined. So this will return false and if that's the case, the right side will never run cuz the right side will only run if the left side is true. So, mostly, it depends on how much control you need and whether you need to do something on the condition that the user does not provide a callback function. It's up to you.

Back to the top