jQuery Table Striping Bug
I have been using jQuery to do table striping, and up until today, I have not had any problems with it.
I had just been using the :even and :odd selectors to add classes to each table row.
Here is the code that I have been using:
$(document).ready(function(){
$("table.striped tbody tr:odd").addClass("odd");
$("table.striped tbody tr:even").addClass("even");
});
Seems easy enough. Then I just styled the odd table rows like so:
table.striped tr.odd td { background-color: #f0f0f4; }
One thing to note is that the :even and :odd selectors are zero-indexed, so the first table row will have a class of even, and not odd. Here is an example showing this simple striping.
Multiple Striped Instances
The situation that I had today had two different tables that were being striped. So based on the code, you would think that there wouldn’t be a problem. Here is the example with two striped tables on the same page.
Weird, so it looks like the first table row in the second striped table has a class of even instead of odd. I thought that the client may not like that because the two tables were not consistent, so I tried to think of another way to do the striping.
The nth Child
So based on the documentation, it looks like the nth child selector would be the solution. I just modified my JavaScript like so:
$(document).ready(function(){
$("table.striped tbody tr:nth-child(odd)").addClass("odd");
$("table.striped tbody tr:nth-child(even)").addClass("even");
});
As a note, the nth child selector is not zero indexed, so the first table row will have a class of odd instead of even. Here is the fixed example.
Conclusion
From what I can tell, this does not appear to be a browser problem, but a bug in jQuery. I have checked this in Firefox, Safari, IE6 and IE7.








so basically the counter is not being reset when performing yet another “table striping”-session, aint it?
I havent looked into the source yet, but normally you would create a oddeven-chooser-function like this, ie. using a row counter and then % 2 (true = odd, false = even).
cu, w0lf.
I don’t think this is a jQuery bug. In fact, I would consider this a feature. In your selector, you are telling jQuery to collect all TRs that are inside TABLEs with the “striped” class that appear in the document and then differentiate between the even and odd ones. You aren’t telling jQuery to reset the counter when it encounters a new table. While this might seem like something that should happen automatically, there are many use cases where you wouldn’t want that to happen. I think this is all just part of the power of jQuery. So the easy fix is to just group each table into its own collection, which gives each on its own index. And you could do that with something like this…
I’m not saying your solution is wrong. This is just another solution that would work too. There are probably a 100 other ways to do it as well.
Nice post, but Andy is right. I tried his changes on your tables, and they work like a charm. Sometimes the obvious isn’t so obvious, and I keep stumbling upon dozens of ways to do similar things in jQuery.
Keep up the good work!
@Andy and Pete-
I see what you are saying. But with that, wouldn’t the nth-child selector work the same way?
Thanks for this, you just saved me a ton of time. I thought it was a jQuery bug at first too, but Andy’s explanation makes it all so clear.
Funny enough, I like everyone else thought this was a jQuery bug. After doing my own debugging and realizing the table rows were being indexed, I decided to do some searching around.
It seems no-one else immediately has the solution you did. Your solution worked beautifully and I’m very thankful for this tutorial. Great work, it’s really appreciated!
nth-child, who would’ve known.
-Tim
Thanks :D
Perfect. Exactly what I was looking for. I’m doing this instead of the Ruby on Rails cycle helper. You have to reset the cycle helper every time you want to use it on a new table and it gets annoying. This is much better. Thanks. It makes more sense to do it this way too.