Introduction to DOM Traversal
Okay, so one of the things you're going to see on job descriptions all over the place or on job postings is DOM traversal. You're going to see things like "able to traverse the DOM with ease," "able to bend the DOM to your will," skilled at DOM interaction.
And what that means is you kind of know your way around the Document Object Model, which is what the DOM stands for. And what the Document Object model is, is when your browser reads your HTML file, it actually turns each one of these elements you've made into an element in the browser that JavaScript can talk to, that CSS styles can be applied to. And so kind of when the browser reads all three technologies, it creates the DOM and then it can render it for the viewer to see.
And so when you interact with JavaScript, you're not actually interacting with your HTML code, you're interacting with what the browser built from your HTML code. You're interacting with the DOM. So when you see things like that in job descriptions, they're looking for, "Can you easily find specific and sometimes complicated things out of the DOM and work with them?"
And that's where jQuery really shines. It is actually primarily a DOM traversal library. It's made to do things that would normally be very complex with JavaScript alone. It makes them very easy. So let's get into DOM traversal with jQuery.
Basic Element Selection with first(), last(), and eq()
I'm actually going to start over here with the console because it makes it a little easier. We know that you can go li and find all the li elements. There you go, that found all my li elements on the page.
A cool thing you can do is you can go .first() and that's going to find your first one on the page. And then you can go .last() and that's going to find the last one on the page, which is not actually the last one in my list, it's the last one on the entire page, which is this li which is inside of another li.
So let's say I can actually go .first() and I can .hide() it. There you go, the first one's hidden. I can .show() it again. I can go eq() which will actually get me an index. So if I go eq(0), that's going to get me the first index, which is actually the same as .first(). But I can actually go eq(1) which will give me the second one. So the eqs would go 0, 1, 2, three, which is the li right here, three, then four, five, six. So I have seven lis on the page, eq(0) through 6. So that would kind of be how to access those.
Navigating with children() and siblings()
Let's look at children(). So let's say I wanted to get ul:first. Here's another way you can do it if you want to do it in the selector—same thing. children() will get me all the lis that are direct children of my element. So if I look back over here at my HTML code, I have a child li, child li, child li. These lis down here will not show up in that list because it's only getting my first children. So that's kind of a way to help narrow that selection down if I only wanted to hide the children of list. That would be how I do that.
Another one is siblings(). So if I want to go li:first, siblings(), then that's going to give me all the siblings of this guy, but this guy will not be in the list because it's just my siblings. So that's those three elements there.
Traversing Up with parent() and Chaining Methods
Let's see, there's another one then that would be parent(). li:first.parent()... and that's going to give me the ul that is my parent. And you can actually keep chaining that up. So let me go li:eq(4), which will be this guy, eq(4), that's him right there. And then eq(4).parents() is going to give me the sublist which is ul. And if I go .parent().parent() then that's going to give me the li that that's a part of. And you can just keep going up the chain and that's going to give me the list.
Another thing I can do is go .parent().parent().prev(). So now I'm going to this li and I'm going .parent(), which is the whole ul. I'm going .parent() again, which is this li, and I go .prev(). That's going to go to the previous sibling now. So that should give me this three right here. And there you go. Yep, you have it. So now if I go .prev().prev(), now I'm going up to two. So I'm going all the way up the chain, I'm going to the previous, to the previous. And now if I go .prev().prev().next(), which makes absolutely no sense, why would I go back only to go forward? I'm back up to three. Probably an easier way to do this would go li:first.next(), which is going to give me the same as eq(1). So that's kind of how you start moving around things.
Practical Examples: Event Handling and Manipulation
Let me show you a couple use cases of how you could do stuff like this. I'm going to go $('li').on('click', ...) and I'm going to go $(this).next().hide(). So whenever I click, I'm just going to hide the next li. So I'm gonna click on you, and number two's gone. And now I'm going to click on you and number four is gone. If I click on you, nothing happens because number two still exists, it's just hidden. So if I would actually go .next().remove(), I could actually keep doing this over and over again. There you go. So that's kind of how that works.
Another thing that I could do is I could hide all the siblings(). I'll just remove them, why not? Why make them go away when you can make them gone forever. So now whichever one you click on is the one that's going to stay. You notice this one's blue, it's because it has a class of special. I made this simple rule that anything with special gets blue. So what I could actually do is I could make all my siblings have a class of special whenever you click on something. So now I didn't become special but all my siblings became special. And what I could actually do is make sure that my class special gets removed if I do have it. So that way, there you go. Now whatever I click on, all my siblings will get the special class, but I won't have the special class.
What's another thing you could do? I could actually go .parent() and add the special class to my parent. So now when I click on this, the parent gets a special class, so everybody within it gets it. So that's kind of another thing that you can do.
Advanced Traversal: closest(), find(), and filter()
I can also go closest(). I don't think I did closest() yet. And then closest() you have to give it something. So I'm gonna go .list. So it's going to go up the chain 'til it finds something with a class of list. So basically no matter what li I click on, it's going to go all the way up the chain, "are you a list? are you a list? oh, you're a list." And so then I'm going to add the class to that. So now I can click here and it goes all the way up, adds special to the entire thing.
Let's see, I'll give you a couple more examples before I leave you guys for now. You could do .filter(). So let's say whenever I click on list, I'm going to go .find(). I'm going to go find all the lis within my element. So whenever I click anywhere on this list, I'm going to find all the lis within list and I'm going to remove... I'll do addClass('special'), same thing as I've been doing. So this should do just what we've been doing. There we go. But let's say I only actually want to add the class to the first li of each one. I can do that guy. So only the first elements are going to get it now, the first element.
I could also go .filter('.special'). And I'll actually do a .removeClass() here. Hope I'm not going too fast for you at this point. So whenever I click on anything inside of list, this is going to be list because that's what my selector was here. I'm going to find any li in it, filtered by .special. So I'm going to find all the lis, I'm going to filter them down to where only special exists, and I'm going to remove special. So now I'm clicking and special's gone.
Of course, an easier way to do this would just go .find('.special'). But then I couldn't teach you about the filter method, now could I? There you go, exact same thing. So find() is awesome. Another great thing about find() is it's really, really fast because it's only looking in this element. It's not having to look at my whole page. I could get around this by doing this exact same thing here. Whenever I click, $('.special').removeClass('special'), right? That's easy. Exact same thing. But now it had to search my entire page to find one item with a class of special. That's not very efficient JavaScript. So I'm going to stay within the element that we're working with. I'm going to find special inside of it and then I'm going to remove it.
Conditional Logic with .is()
Another thing that I can do is I can do an action only if... Let me do another thing. So any li I click on, I can do an if and alert('special'). So if it's a special one that I clicked on, I want to alert special. So of course we can do this. I mean that's easy. You know, anytime you click on .special, alert special. Of course, should do that. Oh, this.if is... so now whenever I click on special, it alerts special. Awesome. Okay.
Uhm, let's say I want to do other stuff to every other li. Say in here, "other stuff happens." Uhm, oh, like let's say I want to hide() it. And if I'm hiding a special one, I also want to alert special. So I can go, if ($(this).is('.special')), if this is special, alert special. So now whenever I click on any li, it's going to hide it. And that's going to hide it and say, haha, special.
Another thing I can do, if ($(this).is(':not(.special)')), alert not special. Not special. And not special. So that's kind of how you can do those things.
Solving Event Bubbling and Final Thoughts
While I'm on this, I'm hiding every li that gets clicked on. And look at this, when I click on one of these sub-lis over here, it hides the entire menu. That's because when I click, I'm clicking on you, and I'm clicking on you, because I'm inside of you at the same time. So there's a listener for both of these lis.
Couple ways you could get around this. I could just target .sublist. I can only hide ones when I click on the .sublist... sorry, .sublist ul li. So now I'm only going to... I'm only listening to lis on the sublist. These aren't doing anything. Okay, that's one way around it. But say I still wanted to do a bunch of other stuff to all lis. So I want to do other stuff to all lis and I only want to hide the li if it's on the sublist. So I could go if ($(this).parent().is('.sublist')). So if the parent is a sublist, then I'm going to hide it, and if it's not, I'm not going to do anything else. So now I'm doing other stuff. Like here, let me say I want a console.log. So now whenever I click on any li, it's going to log down here that I did... fix this, there we go. When I click on any li, it's going to say "clicked on Li," as you notice down there that number keeps going up. And when I click on you, it's going to also log and it's going to hide.
So that's kind of how we can do some smarter things like that. I think that just about covers it. I tried to go fast for those of you guys that are a little more comfortable, you can get it and be done, and some of you guys may want to rewatch this video. But that's about it. I hope you enjoyed learning about DOM traversal with jQuery.