jQuery Interacting with Other Code
We learned with our sorting and paging code that we can't treat the various features we write as islands. The behaviors we build can interact in sometimes surprising ways; for this reason, it is worth revisiting our earlier efforts to examine how they coexist with the new filtering capabilities we have added.
Row Striping
The advanced row striping we put in place earlier is confused by our new filters. Since the tables are not re-striped after a filter is performed, rows retain their coloring as if the filtered rows were still present.
To account for the filtered rows, the striping code needs to be able to find them. We can add a class on the rows when they are filtered:
Sample Code
$(document).ready(function() {
$('table.filterable').each(function() {
var $table = $(this)
$table.find('th').each(function (column) {
if ($(this).is('.filter-column')) {
var $filters = $('</p><br>
<div class="filters">
<h3>Filter by ' +
$(this).text() + ':</h3>
</div>
')
var keywords = {}
$table.find('tbody tr td').filter(':nth-child(' + (column +
1) + ')').each(function() {
keywords[$(this).text()] = $(this).text()
})
$('
<div class="filter">all</div>
').click(function() {
$table.find('tbody tr').show().removeClass('filtered')
$(this).addClass('active').siblings().removeClass('active')
$table.trigger('stripe')
}).addClass('clickable active').appendTo($filters)
$.each(keywords, function (index, keyword) {
$('
<div class="filter"></div>
').text(keyword).bind('click',
{'keyword': keyword}, function(event) {
$table.find('tbody tr').each(function() {
if ($('td', this).filter(':nth-child(' + (column + 1) +
')').text() == event.data['keyword']) {
$(this).show().removeClass('filtered')
}
else if ($('th',this).length == 0) {
$(this).hide().addClass('filtered')
}
})
$(this).addClass('active').siblings().removeClass('active')
$table.trigger('stripe')
}).addClass('clickable').appendTo($filters)
})
$filters.insertBefore($table)
}
})
})
})
Copyright exforsys.com
Whenever the current filter changes, we trigger the stripe event. This uses the same trick we implemented when making our pager aware of sorting—adding a new custom event. We have to rewrite the striping code to define this event:
Sample Code
$(document).ready(function() {
$('table.striped').each(function() {
$(this).bind('stripe', function() {
var rowIndex = 0
$('tbody tr:not(.filtered)', this).each(function(index) {
if ($('th',this).length) {
$(this).addClass('subhead')
rowIndex = -1
} else {
if (rowIndex % 6 < 3) {
$(this).removeClass('odd').addClass('even')
}
else {
$(this).removeClass('even').addClass('odd')
}
}
rowIndex++
})
})
$(this).trigger('stripe')
})
})
Copyright exforsys.com
The selector to find table rows now skips filtered rows. We also must remove obsolete classes from rows, as this code may now be executed multiple times. With both the new event handler and its triggers in place, the filtering operation respects row striping:
