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.
10 Comments
fwolf
06.18.2008so 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.
Andy Couch
06.18.2008I 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…
$(document).ready(function(){$("table.striped").each(function(){
$(this).find("tbody tr:odd").addClass("odd");
$(this).find("tbody tr:even").addClass("even");
});
});
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.
Pete
06.18.2008Nice 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!
Trevor
06.18.2008@Andy and Pete-
I see what you are saying. But with that, wouldn’t the nth-child selector work the same way?
Joe
03.30.2009Thanks 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.
Tim Selaty
12.23.2009Funny 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
YoHang
02.11.2010Thanks :D
Brandon Buttars
03.01.2010Perfect. 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.
raffaello
04.11.2010Definitely a good post. Tank you for being so clear and helpful.
Thanks also everybody for your posts.
Cheers.
Roman Kopac
05.19.2010It’s not a bug. Andy already explained why :even and :odd work as they do. In your case, the :nth-child works because it counts the index of the child in regard to its particular parent. So the counter is reset for each table.
——-