JQuery_ Novice to Ninja - Earle Castledine [124]
chapter_08/04_expandable_tree/script.js (excerpt)
.handle {
background: transparent url(tree-handle.png) no-repeat left top;
display:block;
float:left;
width:10px;
height:10px;
cursor:pointer;
}
.closed { background-position: left top; }
.opened { background-position: left -10px; }
The code for the tree is remarkably simple, thanks to the recursive nature of a tree: we just have to do one small piece of code, and attach it to each subcategory. Our plan of attack for creating the expanding/collapsing tree effect is to first hide all of the nested ul categories. Then we’ll add in a new element before the category title that contains a click event handler—this will open and close its branch:
chapter_08/04_expandable_tree/script.js (excerpt)
$('#celebTree ul')
.hide()
.prev('span')
.before('')
.prev()
.addClass('handle closed')
.click(function() {
// plus/minus handle click
});
Six chained actions. Bet you’re feeling some of that jQuery power coursing through your veins right about now! Here we see where consistent markup helps us out: in each subcategory list we look for the previous span element—that’s the subcategory title. Then we insert a new span element right before the title.
Because our handle was added before the title, we need to move back to it with the prev action. We add the handle and closed (it’s closed by default because of the hide action) classes to it, and an event handler for when it’s clicked.
At this stage the tree will be fully collapsed, with our brand-new handle prepended to the titles. All that’s left to do is toggle the branches when we click on it:
chapter_08/04_expandable_tree/script.js (excerpt)
// plus/minus handle click
$(this)
.toggleClass('closed opened')
.nextAll('ul')
.toggle();
When the handle is clicked, we toggle the closed and opened classes with toggleClass. If you specify multiple class names with toggleClass, any specified class that exists on the element is removed, and any that are absent from the element are added.
Tip: Advanced toggleClass
Another neat trick of toggleClass is that it accepts a second parameter: a Boolean value that specifies whether the class should be added or removed. This might sound strange, but it’s a nice shortcut. Consider this code:
if (x == 1) {
$(this).addClass('opened');
} else {
$(this).removeClass('opened');
}
With the toggleClass(class, switch) syntax, we can replace the if statement with the following concise syntax:
$(this).toggleClass('opened', x == 1);
Finding the subcategory that we need to open and close is easy, thanks to the nextAll action. jQuery will check the next sibling, see that it’s a span element (the category title), filter it out based on our expression, and move to the next sibling … which is a ul item. Bingo! We just toggle this and the tree swings open and closed.
Event Delegation
Event delegation is a topic that’s applicable everywhere, but is particularly important if you’re dealing with large trees. The idea is that instead of applying individual event handlers to every node in your tree, you apply a single event handler to intercept the click—and then figure out who the click was aimed at and run the appropriate action.
If you’ve been following along closely this might sound a bit familiar to you. We covered the live method in the section called “Prepare for the Future: live and die” in Chapter 6. live handles event delegation for you—that’s the magic that makes it possible—but it comes with a potential gotcha that you need to be aware of.
To acquire a better understanding of how event delegation works and why it is important, let’s use it for real. We’ll start with the following HTML that displays our products in a categorized list:
chapter_08/05_event_delegation/index.html (excerpt)
Selection:
--Choose a celebrity--
A-List
- Beau Dandy