Collapsing and
expanding sections
When a large set of data
is divided into sections, it can be useful to hide information that we
aren't interested in at the moment. In our table of news articles, rows
are grouped by year; collapsing, or hiding, a year of articles can be a convenient way
to get a broad view of all of the table's data without having to scroll
so much.
To make the sections of the
news article table collapsible, we first need to create a page element
that will be used to trigger the behavior. One standard interface for
collapsible items is a minus sign, with a corresponding plus sign for
expandable items. We'll insert the icon with JavaScript, following
standard progressive enhancement
techniques.
$(document).ready(function() {
var collapseIcon = '../images/bullet_toggle_minus.png';
var collapseText = 'Collapse this section';
var expandIcon = '../images/bullet_toggle_plus.png';
var expandText = 'Expand this section';
$('table.collapsible tbody').each(function() {
var $section = $(this);
$('<img />').attr('src', collapseIcon)
.attr('alt', collapseText)
.prependTo($section.find('th'));
});
});
We have stored the
locations of the icons, as well as their alternate textual
representations, in variables at the beginning of the function. This
allows us to refer to them easily, and provides a simple way to make
changes if necessary. We've done the image injection in an .each() loop, which will prove convenient later as we
will need to refer to the enclosing<tbody> element again; it will be available to us
through the $section variable we've defined here.
Next, we'll need to make the
icons trigger the collapsing and expanding of rows. The addition of a
clickable class provides the
necessary user feedback, and a class on the<tbody> element helps us keep track of whether the rows are
currently visible or not.
$(document).ready(function() {
var collapseIcon = '../images/bullet_toggle_minus.png';
var collapseText = 'Collapse this section';
var expandIcon = '../images/bullet_toggle_plus.png';
var expandText = 'Expand this section';
$('table.collapsible tbody').each(function() {
var $section = $(this);
$('<img />').attr('src', collapseIcon)
.attr('alt', collapseText)
.prependTo($section.find('th'))
.addClass('clickable')
.click(function() {
if ($section.is('.collapsed')) {
$section.removeClass('collapsed')
.find('tr:not(:has(th))').fadeIn('fast');
$(this).attr('src', collapseIcon)
.attr('alt', collapseText);
}
else {
$section.addClass('collapsed')
.find('tr:not(:has(th))').fadeOut('fast');
$(this).attr('src', expandIcon)
.attr('alt', expandText);
}
});
});
});
When a click occurs, we
do the following:
1. Add or remove the
collapsed class on the<tbody>
element, to keep track of the current state of the table section.
2.
Locate all rows in the section that do not contain headings, and show
or hide them using a fading transition.
3.
Toggle the current state of the icon, changing its src and
alt attributes to reflect the action it
will now trigger when clicked.
With this code in place, clicking on the Collapse this section icon next to 2007 makes the table look like this:
The 2007 news articles aren't
removed; they are just hidden until we click the Expand this section icon that now appears in that row.
Table rows
present particular obstacles to animation, since browsers use different
values (table-row and block) for their visible display
property. The .hide() and
methods, without animation, are always safe to use with table rows. If
animation is desired, .fadeIn() and .fadeOut() can be
used as well. .show()