programming4us
programming4us
MOBILE

jQuery 1.3 : Modifying table appearance (part 1) - Row highlighting

2/24/2011 3:45:58 PM
We have now looked at some ways of ordering the rows of data in a table to provide assistance to the user in finding the desired information. It is often the case, though, that there is still a lot of data to sift through after any sorting or paging is performed. We can assist the user by manipulating not just the order and quantity of displayed rows, but the appearance of those that are shown.

Row highlighting

One practical way to guide the user's eye is to highlight rows to give a visual cue about what data is important. To examine some highlighting strategies, we need a table to work with. This time, we'll start with a table of news items. The table will be a little more complicated than the last; it will include some rows used as subheadings, in addition to a main heading row. The HTML structure is as follows:

<table>
<thead>
<tr>
<th>Date</th>
<th>Headline</th>
<th>Author</th>
<th>Topic</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="4">2008</th>
</tr>
<tr>
<td>Sep 28</td>
<td>jQuery, Microsoft, and Nokia</td>
<td>John Resig</td>
<td>third-party</td>
rows, table appearanceshighlighting</tr>
...
<tr>
<td>Jan 15</td>
<td>jQuery 1.2.2: 2nd Birthday Present</td>
<td>John Resig</td>
<td>release</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="4">2007</th>
</tr>
<tr>
<td>Dec 8</td>
<td>jQuery Plugins site updated</td>
<td>Mike Hostetler</td>
<td>announcement</td>
</tr>
...
<tr>
<td>Jan 11</td>
<td>Selector Speeds</td>
<td>John Resig</td>
<td>source</td>
</tr>
</tbody>
...
</table>


Note the use of multiple<tbody> sections. This is valid HTML markup for grouping sets of rows together. We have placed the section subheadings within these groupings, using<th> elements to set them off. With basic CSS added, this table renders as follows:

Row striping

We have already seen one simple example of row highlighting earlier in this chapter, and before that in Chapter 2. Striping rows is a common way to guide the user's eye across multiple columns accurately.

As we have seen, row striping can be as simple as a couple of lines to add classes to odd and even rows:

$(document).ready(function() {
$('table.striped tr:odd).addClass('odd');
$('table.striped tr:even).addClass('even');
});

While this code works fine for simple table structures, if we introduce additional rows we do not want to be striped (such as the subheading rows we are using for the years in our table), the basic odd-even pattern no longer suffices. If, for example, the 2006 row would be classified as even, the rows before and after it would both be odd, which is likely not desirable.

We can ensure that our alternating-row pattern begins anew with each years' worth of news items by using the :nth-child() pseudo-class we learned about in Chapter 2:

$(document).ready(function() {
$('table.striped tr:nth-child(odd)').addClass('odd');
$('table.striped tr:nth-child(even)').addClass('even');
});

Each group of rows now begins with an odd row, but the subheading rows are included in this calculation. So instead, we could exclude the subheading rows from consideration with the :has() pseudo-class:

$(document).ready(function() {
$('table.striped tr:not(:has(th)):odd').addClass('odd');
$('table.striped tr:not(:has(th)):even').addClass('even');
});

Now the subheadings are excluded, but groupings will begin with an odd or even row depending on which classification applied to the previous data row. Reconciling these two behaviors can be a bit tricky; one straightforward option is introducing some explicit iteration using the .each() method.

$(document).ready(function() {
rows, table appearancesstriping$('table.striped tbody').each(function() {
$(this).find('tr:not(:has(th)):odd').addClass('odd');
$(this).find('tr:not(:has(th)):even').addClass('even');
});
});

Now each grouping is striped independently, and subheading rows are excluded from the calculations.

Advanced row striping

These manipulations of odd and even rows have set us up for some more complicated techniques. In particularly dense tables, even alternating row colors can be confusing to the eye, and it can be beneficial to alternate colors at a larger interval. As an example, we will modify the striping of our news table to color its rows three-at-a-time.

In Chapter 2, we introduced the .filter() method for selecting page elements in a very flexible way. Recalling that .filter() can take not just a selector expression, but also a filter function, we can write:

$(document).ready(function() {
$('table.striped tbody').each(function() {
$(this).find('tr:not(:has(th))').filter(function(index) {
return (index % 6) < 3;
}).addClass('odd');
});
});

This code accomplishes a lot in a small space, so let's break it down piece-by-piece.

First, we use the .each() method as before to segment our task neatly by row grouping. We want our three-row stripes to begin anew after each subheading, so this technique allows us to work one section at a time. Then, we use .find() as in our last example to locate all of the rows that do not have<th> elements (and thus are not subheadings).

Now, we need to select the first three elements of this set, skip three elements, and so forth. This is where .filter() comes into play. The filter function takes an argument containing the index of the item within the matched set&mdash;that is, the row number in the section of the table we're examining. If, and only if, our filter function returns true, the element will remain in the set.

The modulo operator (%) provides us with the information we need. The expression index % 6 evaluates to the remainder of the row number when divided by 6; if this remainder is 0, 1, or 2, then we'll mark the row as odd; if it is 3, 4, or 5, the row will be even.

The code, as presented, only marks the odd sets of rows. To also apply the even class, we could write another filter that applied the opposite filter, or we can get a bit more creative:

$(document).ready(function() {
$('table.striped tbody').each(function() {
$(this).find('tr:not(:has(th))').addClass('even')
.filter(function(index) {
return (index % 6) < 3;
}).removeClass('even').addClass('odd');
});
});

Here we apply the even class to all of the rows, and remove it if we add the odd class. Our table now has stylish alternating row groupings, which begin anew with each new section of the table.

Interactive row highlighting

Another visual enhancement that we can apply to our news article table is row highlighting based on user interaction. Here we'll respond to clicking on an author's name by highlighting all rows that have the same name in their Author cell. Just as we did with the row striping, we can modify the appearance of these highlighted rows by adding a class:

#content tr.highlight {
rows, table appearanceshighlighting, with user interactionbackground: #ff6;
}

It's important that we give this new highlight class adequate specificity, so that the background color will override that of the even and odd classes.

Now we need to select the appropriate cell and attach behavior to it using the .click() method:

$(document).ready(function() {
rows, table appearanceshighlighting, with user interactionvar $authorCells = $('table.striped td:nth-child(3)');
$authorCells.click(function() {
// Perform our highlighting here.
});
});


Notice that we use the :nth-child(n) pseudo-class as part of the selector expression that points to the third column where the author information is. In case the table structure were to later change, we would want this constant 3 to be in only one place in the code, so it could be easily updated. For this reason, and for efficiency, we store the result of our selector in the $authorCells variable rather than repeating the selector each time it is needed.

Recall that unlike JavaScript indices, the CSS-based :nth-child(n) pseudo-class begins numbering at 1, not 0.


When the user clicks a cell in the third column, we want the cell's text to be compared to that of the same column's cell in every other row. If it matches, the highlight class will be toggled. In other words, the class will be added if it isn't already there and removed if it is. This way, we can click on an author cell to remove the row highlighting if that cell or one with the same author has already been clicked.

$(document).ready(function() {
var $authorCells = $('table.striped td:nth-child(3)');
$authorCells.click(function() {
var authorName = $(this).text();
$authorCells.each(function(index) {
if (authorName == $(this).text()) {
$(this).parent().toggleClass('highlight');
}
});
});
});

The code is working well at this point, except when a user clicks on two authors' names in succession. Rather than switching the highlighted rows from one author to the next as we might expect, we end up with the highlight class on both groups of rows. To avoid this behavior, we can add an else statement to the code, removing the highlight class for any row that does not have the same author name as the one clicked:

$(document).ready(function() {
var $authorCells = $('table.striped td:nth-child(3)');
$authorCells.click(function() {
var authorName = $(this).text();
$authorCells.each(function(index) {
if (authorName == $(this).text()) {
$(this).parent().toggleClass('highlight');
}
else {
$(this).parent().removeClass('highlight');
}

});
});
});

Now when we click on Rey Bango, for example, we can see all of his articles much more easily:

If we then click on John Resig in any one of the cells, the highlighting will be removed from Rey Bango's rows and added to John's.

Other  
  •  Windows Phone 7 Development : Using Culture Settings with ToString to Display Dates, Times, and Text
  •  Mobile Application Security : SymbianOS Security - Persistent Data Storage
  •  Mobile Application Security : SymbianOS Security - Interprocess Communication
  •  Mobile Application Security : SymbianOS Security - Permissions and User Controls
  •  Windows Phone 7 Development : Building a Trial Application (part 3) - Verifying Trial and Full Mode & Adding Finishing Touches
  •  Windows Phone 7 Development : Building a Trial Application (part 2) - Connecting to a Web Service & Adding Page-to-Page Navigation
  •  Windows Phone 7 Development : Building a Trial Application (part 1) - Building the User Interface
  •  jQuery 1.3 : Table Manipulation - Sorting and paging (part 2) : Server-side pagination & JavaScript pagination
  •  jQuery 1.3 : Table Manipulation - Sorting and paging (part 1) : Server-side sorting & JavaScript sorting
  •  Windows Phone 7 Development : Understanding Trial and Full Modes (part 3) - Simulating Application Trial and Full Modes
  •  
    Top 10 Video Game
    -   Minecraft Mods - MAD PACK #10 'NETHER DOOM!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
    -   Minecraft Mods - MAD PACK #9 'KING SLIME!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
    -   Minecraft Mods - MAD PACK #2 'LAVA LOBBERS!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
    -   Minecraft Mods - MAD PACK #3 'OBSIDIAN LONGSWORD!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
    -   Total War: Warhammer [PC] Demigryph Trailer
    -   Minecraft | MINIONS MOVIE MOD! (Despicable Me, Minions Movie)
    -   Minecraft | Crazy Craft 3.0 - Ep 3! "TITANS ATTACK"
    -   Minecraft | Crazy Craft 3.0 - Ep 2! "THIEVING FROM THE CRAZIES"
    -   Minecraft | MORPH HIDE AND SEEK - Minions Despicable Me Mod
    -   Minecraft | Dream Craft - Star Wars Modded Survival Ep 92 "IS JOE DEAD?!"
    -   Minecraft | Dream Craft - Star Wars Modded Survival Ep 93 "JEDI STRIKE BACK"
    -   Minecraft | Dream Craft - Star Wars Modded Survival Ep 94 "TATOOINE PLANET DESTRUCTION"
    -   Minecraft | Dream Craft - Star Wars Modded Survival Ep 95 "TATOOINE CAPTIVES"
    -   Hitman [PS4/XOne/PC] Alpha Gameplay Trailer
    -   Satellite Reign [PC] Release Date Trailer
    Video
    programming4us
     
     
    programming4us